home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Storage / DragDrp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  91.9 KB  |  2,996 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DragDrp.cpp
  3.  
  4.     Contains:    Implementation of ODDragAndDrop
  5.  
  6.     Owned by:    Douglas Hill
  7.     
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <18>     8/13/96    DM        1376080: use TempDelayBentoFatalError to
  13.                                     ensure old flag value is restored
  14.         <17>     7/18/96    DH        Task: Self-embedding causes crash. Fixed
  15.                                     exception handling in drag receive handler
  16.                                     so return value of Drop is propogated
  17.                                     correctly.
  18.         <16>     7/11/96    DH        1365986    1.1GM: Crash when drag fails and
  19.                                     another drag is attempted. Fixed many stale
  20.                                     object references.
  21.         <15>     6/26/96    DH        #1358088: Subframes allow self-embedding.
  22.                                     This was a part of a more general case of
  23.                                     nested self-embedding. Fixed so that the
  24.                                     checks happen at drag-tracking time
  25.                                     correctly. See also new recipe for marking
  26.                                     frames as part of a drag.
  27.         <14>     6/21/96    DH        1340739: 1.0.xp: Ctl-drag of content to
  28.                                     non-od destination does not remove
  29.                                     original.
  30.                                     1340966: 1.0.x: Avoiding undo when content
  31.                                     dragged to non-OpenDoc target. 1340739:
  32.                                     1.0.xp: Ctl-drag of content to non-od
  33.                                     destination does not remove original.
  34.                                     1353507: 1.0.x: Dragging Scrapbook OpenDoc
  35.                                     clipping to document can cause crash. Added
  36.                                     support for reading clipping files (see
  37.                                     ODDragAndDropEnterHandler).
  38.         <13>     5/31/96    jpa        T10012: Overhauled IsOpenDocDocument. Set
  39.                                     correct creator of files/promises created.
  40.         <12>     5/24/96    jpa        1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
  41.         <11>     5/13/96    DH        1332488 - 1.0.x:User break dragging Edition
  42.                                     file into an OpenDoc window.
  43.                                     1305572 - 1.1MRD:[Cyberdog]Dragging
  44.                                     multiple items *really* slow.
  45.                                     1314704 - 1.0.x: Enourmous performance hit
  46.                                     when dragging numerous items over windows.
  47.         <10>      5/1/96    JA        1314704: Create only one mem container
  48.                                     (_fMemItemContainer) for all dragged-in
  49.                                     non-Bento files.
  50.          <9>    .04.1996    NP        1330731: Don't use stationery property
  51.                                     anymore.
  52.          <8>     4/16/96    DH        Fixed InWindow to ignore a null container.
  53.          <7>      4/9/96    DH        1308248: 1.0.2 Drag of no-part to trash
  54.                                     rejected. Used string resource for no-part
  55.                                     category instead of hard-coding it. Also
  56.                                     made filename of file in Trash when you
  57.                                     drop Nopart into the trash not be garbled.
  58.          <6>      4/8/96    DH        1338112: 1.0.2? Drag Hiliting Problems
  59.          <4>     3/29/96    DM        1296171: delay fatal Bento container errors
  60.                                     when inside drag manager
  61.          <3>     3/15/96    VL        1302780: Use GetFacetUnderPointForDrag
  62.                                     instead of GetFacetUnderPoint so that we
  63.                                     can drop within selection.
  64.          <2>     3/15/96    DH        287259 - 1.0.2 Don't get back what I put in
  65.                                     the scrapbook. Now writes out a memory
  66.                                     container to applications that it reloads
  67.                                     if it is found from Drag and Drop. Also
  68.                                     compatible with Clipboard container type.
  69.                                     1293781 - 1.0.2 DragWithin called out of
  70.                                     order. Fixed ODDragAndDropInWindow so that
  71.                                     it doesn't call DragLeave on the Containing
  72.                                     part unless the embedded part returns True
  73.                                     from DragEnter.
  74.  
  75.     To Do:        
  76.     In Progress:
  77.         
  78. */
  79.  
  80. #ifndef _ALTPOINT_
  81. #include "AltPoint.h"            // Use C++ savvy ODPPoint and ODPRect
  82. #endif
  83.  
  84. #define ODDragAndDrop_Class_Source
  85. #define VARIABLE_MACROS
  86. #include <DragDrp.xih>
  87.  
  88. #ifndef SOM_ODDragItemIterator_xh
  89. #include <DgItmIt.xh>
  90. #endif
  91.  
  92. #ifndef _DRAGPRIV_
  93. #include <DragPriv.h>
  94. #endif
  95.  
  96. #ifndef _STORRSRC_
  97. #include <StorRsrc.h>
  98. #endif
  99.  
  100. #ifndef SOM_Module_OpenDoc_StdProps_defined
  101. #include <StdProps.xh>
  102. #endif
  103.  
  104. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  105. #include <StdTypes.xh>
  106. #endif
  107.  
  108. #ifndef SOM_ODSession_xh
  109. #include <ODSessn.xh>
  110. #endif
  111.  
  112. #ifndef SOM_ODStorageSystem_xh
  113. #include <ODStor.xh>
  114. #endif
  115.  
  116. #ifndef SOM_ODContainer_xh
  117. #include <ODCtr.xh>
  118. #endif
  119.  
  120. #ifndef SOM_ODDocument_xh
  121. #include <Document.xh>
  122. #endif
  123.  
  124. #ifndef SOM_ODDraft_xh
  125. #include <Draft.xh>
  126. #endif
  127.  
  128. #ifndef SOM_ODFrame_xh
  129. #include <Frame.xh>
  130. #endif
  131.  
  132. #ifndef SOM_ODFacet_xh
  133. #include <Facet.xh>
  134. #endif
  135.  
  136. #ifndef SOM_ODWindow_xh
  137. #include <Window.xh>
  138. #endif
  139.  
  140. #ifndef SOM_ODWindowState_xh
  141. #include <WinStat.xh>
  142. #endif
  143.  
  144. #ifndef SOM_ODPart_xh
  145. #include <Part.xh>
  146. #endif
  147.  
  148. #ifndef SOM_ODTransform_xh
  149. #include <Trnsform.xh>
  150. #endif
  151.  
  152. #ifndef SOM_ODTranslation_xh
  153. #include <Translt.xh>
  154. #endif
  155.  
  156. #ifndef _ODMEMORY_
  157. #include "ODMemory.h"
  158. #endif
  159.  
  160. #ifndef _ODNew_
  161. #include "ODNew.h"
  162. #endif
  163.  
  164. #ifndef _EXCEPT_
  165. #include "Except.h"
  166. #endif
  167.  
  168. #ifndef _LINKLIST_
  169. #include "LinkList.h"
  170. #endif
  171.  
  172. #ifndef SOM_ODStorageUnitView_xh
  173. #include <SUView.xh>
  174. #endif
  175.  
  176. #ifndef _BENTOSUPPRESS_
  177. #include "BentoSuppress.h"
  178. #endif
  179.  
  180. #ifndef _STORDEF_
  181. #include "StorDef.h"
  182. #endif
  183.  
  184. #ifndef SOM_CMStorageUnit_xh
  185. #include <CMSU.xh>
  186. #endif
  187.  
  188. #ifndef _PLFMFILE_
  189. #include <PlfmFile.h>
  190. #endif
  191.  
  192. #ifndef _CONSTDEF_
  193. #include "ConstDef.h"
  194. #endif
  195.  
  196. #ifndef _PASCLSTR_
  197. #include <PasclStr.h>
  198. #endif
  199.  
  200. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  201. #include "StdDefs.xh"
  202. #endif
  203.  
  204. #ifndef _LINKDLGS_
  205. #include "LinkDlgs.h"
  206. #endif
  207.  
  208. #ifndef __MEMORY__
  209. #include <Memory.h>
  210. #endif
  211.  
  212. #ifndef __GESTALTEQU__
  213. #include <GestaltEqu.h>
  214. #endif
  215.  
  216. #ifndef __TOOLUTILS__
  217. #include <ToolUtils.h>
  218. #endif
  219.  
  220. #ifndef __ERRORS__
  221. #include <Errors.h>
  222. #endif
  223.  
  224. #ifndef __SCRIPT__
  225. #include <Script.h>
  226. #endif
  227.  
  228. #ifndef __PACKAGES__
  229. #include <Packages.h>
  230. #endif
  231.  
  232. #ifndef __APPLEEVENTS__
  233. #include <AppleEvents.h>
  234. #endif
  235.  
  236. #ifndef _ISOSTR_
  237. #include <ISOStr.h>
  238. #endif
  239.  
  240. #ifndef __ALIASES__
  241. #include <Aliases.h>
  242. #endif
  243.  
  244. #ifndef __FOLDERS__
  245. #include <Folders.h>
  246. #endif
  247.  
  248. #ifndef _BARRAY_
  249. #include <BArray.h>
  250. #endif
  251.  
  252. #ifndef SOM_ODNameSpaceManager_xh
  253. #include <NmSpcMg.xh>
  254. #endif
  255.  
  256. #ifndef SOM_ODValueNameSpace_xh
  257. #include <ValueNS.xh>
  258. #endif
  259.  
  260. #ifndef _TEMPOBJ_
  261. #include <TempObj.h>
  262. #endif
  263.  
  264. #ifndef _STORUTIL_
  265. #include "StorUtil.h"
  266. #endif
  267.  
  268. #include <string.h>
  269.  
  270. #ifndef _ODDEBUG_
  271. #include "ODDebug.h"
  272. #endif
  273.  
  274. #ifndef _NMSPCUTL_
  275. #include <NmSpcUtl.h>
  276. #endif
  277.  
  278. #ifndef _STDTYPIO_
  279. #include <StdTypIO.h>
  280. #endif
  281.  
  282. #ifndef __DIALOGS__
  283. #include <Dialogs.h>
  284. #endif
  285.  
  286. #ifndef _INFOUTIL_
  287. #include <InfoUtil.h>
  288. #endif
  289.  
  290. #ifndef __ICONS__
  291. #include <Icons.h>
  292. #endif
  293.  
  294. #ifndef __FINDER__
  295. #include <Finder.h>
  296. #endif
  297.  
  298. #ifndef _POUTILS_
  299. #include <POUtils.h>
  300. #endif
  301.  
  302. #ifndef _OPENHASH_
  303. #include <OpenHash.h>
  304. #endif
  305.  
  306. #ifndef _ITEXT_
  307. #include <IText.h>
  308. #endif
  309.  
  310. #ifndef _USERSRCM_
  311. #include <UseRsrcM.h>
  312. #endif
  313.  
  314. #ifndef _DLOGUTIL_
  315. #include <DlogUtil.h>
  316. #endif
  317.  
  318. #ifndef _DRGDPDEF_
  319. #include "DrgDpDef.h"
  320. #endif
  321.  
  322. #ifndef __DIALOGS__
  323. #include <Dialogs.h>
  324. #endif
  325.  
  326. #ifndef _CTYPE
  327. #include <ctype.h>
  328. #endif
  329.  
  330. static FSSpec gTmpFileFSSpec;
  331. static FSSpec gTargetFSSpec;
  332. static boolean gIsResolvingPromise = kODFalse;
  333.  
  334. //==============================================================================
  335. // Prototyping
  336. //==============================================================================
  337.  
  338. extern ODBoolean gODBentoFatalErrorHasOccurred; // SessHdr.cpp
  339. extern ODBoolean gODDelayBentoFatalError; // SessHdr.cpp
  340. extern ODBoolean gODSuppressBentoFatalError; // SessHdr.cpp
  341. extern void ODBentoFatalError(ODBoolean allowSuppress); // SessHdr.cpp
  342.  
  343. static pascal OSErr MyDragTrackingHandler(
  344.         short message,
  345.         WindowPtr theWindow,
  346.         void* handlerRefCon,
  347.         ODPlatformDragReference theDrag);
  348.  
  349. static pascal OSErr    MyReceiveDropHandler(
  350.         WindowPtr theWindow,
  351.         void* handlerRefCon,
  352.         ODPlatformDragReference theDrag);
  353.  
  354. static pascal OSErr  MySendDataProc(
  355.         FlavorType theType,
  356.         void* refCon,
  357.         ItemReference theItem,
  358.         ODPlatformDragReference theDrag);
  359.  
  360. static OSErr ODPascal ReplaceFileAEHandler(
  361.         const AppleEvent* replaceFileEvent,
  362.         AppleEvent* reply,
  363.         long refCon);
  364.  
  365. static void RespecifyToTempFolder(PlatformFile* file);
  366. static OSErr CreateReplaceFileEvent(Environment* ev, AppleEvent* replaceFileEvent, ODSession* session, ProcessSerialNumber* psn);
  367. static OSErr SetupReplaceFileEvent(Environment* ev, AppleEvent* replaceFileEvent, FSSpec* sourceFileSpec, FSSpec* destFileSpec);
  368. static OSErr SendReplaceFileEvent(AppleEvent* replaceFileEvent, ProcessSerialNumber* psn);
  369. static OSErr DisposeReplaceFileEvent(AppleEvent* replaceFileEvent);
  370. static ODBoolean DragItemHasFlavor(ODPlatformDragReference theDrag, ItemReference itemID, OSType    theType);
  371. static OSErr CloneIntoFile(Environment* ev, ODDragItem* theDragItem, FSSpec dropFSSpec);
  372. static void CloneIntoFlavor(Environment* ev, ODDragAndDrop* dad, ODDragItem* theDragItem, 
  373.                                 ODPlatformDragReference theDrag, ItemReference theItem, FlavorType theType,
  374.                                 FSSpec dropFSSpec);
  375. static boolean MakeUniqueFilename( Environment *ev, ODSession* session, ODStorageUnit *su, FSSpec *spec );
  376. static OSType GetStorageUnitOSType( Environment *ev, ODStorageUnit *su );
  377. static OSErr CopyToDragItemInChunks(Environment* ev,
  378.                                 FlavorType theType,
  379.                                 ItemReference theItem,
  380.                                 ODPlatformDragReference theDrag,
  381.                                 ODDragItem* theDragItem);
  382. static OSErr CopyFromDragItemInChunks(Environment* ev,
  383.                                 FlavorType theType,
  384.                                 ItemReference theItem,
  385.                                 ODPlatformDragReference theDrag,
  386.                                 ODStorageUnitView* destSUView);
  387.  
  388. static OSErr CopyMemContainerToDragItemInChunks(Environment* ev,
  389.                                 ODSession* theSession,
  390.                                 FlavorType theType,
  391.                                 ItemReference theItem,
  392.                                 ODPlatformDragReference theDrag,
  393.                                 ODDragItem* theDragItem);
  394.  
  395. static ODHandle CloneToTempMemContainer( Environment* ev, ODMemDragItem* tempDItem, ODSession* theSession );
  396. static void SetFinderInfo(Environment* ev, ODStorageUnit* su, PlatformFile* file);
  397. static void    SetIconFamily(Environment* ev, ODStorageUnit* fromSU, PlatformFile* file);
  398. static OSErr GetDropFSSpec(ODPlatformDragReference theDrag, FSSpec& dropFSSpec);
  399. static boolean IsTrashFolder(FSSpec dropFSSpec);
  400. static boolean IsFrontProcess();
  401. static ODBoolean IsOpenDocClipping( HFSFlavor* hfsFlavor);
  402. static ODHandle ReadClippingFileOpenDocData( HFSFlavor* hfsFlavor );
  403. static ODBoolean IsNestedSelfEmbedding( ODDragAndDrop *somSelf, Environment *ev, ODFrame* destFrame );
  404.  
  405. #ifdef ODDebug_DragAndDrop
  406.  
  407. #ifndef SOM_ODStorageUnitCursor_xh
  408. #include <SUCursor.xh>
  409. #endif
  410.  
  411. void PrintDragReference(ODPlatformDragReference dragRef, char* header);
  412. void PrintStorageUnit(Environment* ev, ODStorageUnit* su, char* header);
  413. #endif
  414.  
  415. #pragma segment ODDragAndDrop
  416.  
  417. #include "DragDrpB.cpp"    // Platform-independent methods, if any
  418.  
  419.  
  420. SOM_Scope ODBoolean  SOMLINK ODDragAndDropShowPasteAsDialog(ODDragAndDrop *somSelf, Environment *ev,
  421.         ODBoolean canPasteLink,
  422.         ODPasteAsMergeSetting mergeSetting,
  423.         ODFacet* facet,
  424.         ODTypeToken viewType,
  425.         ODStorageUnit* contentSU,
  426.         ODPasteAsResult* result)
  427. {
  428.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  429.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropShowPasteAsDialog");
  430.  
  431.     SOM_TRY
  432.  
  433.     THROW_IF_NULL(facet, kODErrNullFacetInput);
  434.     THROW_IF_NULL(contentSU, kODErrIllegalNullStorageUnitInput);
  435.     THROW_IF_NULL(result, kODErrNullPasteAsResultInput);
  436.  
  437.     ODBoolean returnValue = ShowPasteAsDialog(
  438.                                 canPasteLink, 
  439.                                 mergeSetting,
  440.                                 (somSelf->GetDropResult(ev) == kODDropMove),
  441.                                 contentSU,
  442.                                 facet, 
  443.                                 viewType, 
  444.                                 result);
  445.  
  446.     return returnValue;
  447.  
  448.     SOM_CATCH_ALL
  449.     SOM_ENDTRY
  450.     return kODFalse;
  451. }
  452.  
  453. SOM_Scope void  SOMLINK ODDragAndDropInitDragAndDrop(ODDragAndDrop *somSelf, Environment *ev,
  454.         ODSession* session)
  455. {
  456.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  457.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropInitDragAndDrop");
  458.  
  459. SOM_TRY
  460.  
  461.     _fSession = session;
  462.  
  463.     somSelf->InitObject(ev);
  464.     
  465.     long  gestaltResult;
  466.     OSErr result;
  467.  
  468.     // Get the current process for background drag
  469.     _fPSN = (ProcessSerialNumber*) ODNewPtr(sizeof(ProcessSerialNumber));
  470.     GetCurrentProcess(_fPSN);
  471.     
  472.     _fReplaceFileEvent = (AppleEvent*) ODNewPtr(sizeof(AppleEvent));
  473.     CreateReplaceFileEvent(ev,
  474.         _fReplaceFileEvent,
  475.         session,
  476.         _fPSN);
  477.  
  478.     _fFacetsRejected = new OpenHashTable(OpenHashTable::StdEqual, OpenHashTable::StdHash, kODNULL);
  479.     _fFacetsRejected->Initialize(kODInitialNumEntries,
  480.                                     sizeof(ODFacet*),
  481.                                     sizeof(ODFacet*));
  482.         
  483.     // Check if the drag manager is present
  484.     result = Gestalt(gestaltDragMgrAttr, &gestaltResult);
  485.     if (result != noErr)
  486.         THROW_M(result, "Error from Gestalt");
  487.  
  488.     // The mysterious 31 is the bit position as BitTst uses a convention opposite to MC68000
  489.     if (BitTst(&gestaltResult, (31 - gestaltDragMgrPresent)) == false) {
  490.         THROW_M(kODErrNoDragManager, "No drag manager present");
  491.     }
  492.     else {
  493.         // Install the default tracking handler for this application (session)
  494.         _fTrackingHandler = NewDragTrackingHandlerProc(&MyDragTrackingHandler);
  495.         result = InstallTrackingHandler(_fTrackingHandler, NULL, (void *) somSelf);
  496.         ASSERTM(result == noErr, result, "Error from InstallTrackingHandler");
  497.         
  498.         // Install the default receive handler for this application (session)
  499.         _fReceiveHandler = NewDragReceiveHandlerProc(&MyReceiveDropHandler);
  500.         result = InstallReceiveHandler(_fReceiveHandler, NULL, (void *) somSelf);
  501.         ASSERTM(result == noErr, result, "Error from InstallReceiveHandler");
  502.     
  503.         // Create a UPP for MySendDataProc which we will use later inside ::StartDrag
  504.         _fSendDataHandler = NewDragSendDataProc(MySendDataProc);
  505.     
  506.         _fWindowState = _fSession->GetWindowState(ev);
  507.     
  508.         _fStorageSystem = _fSession->GetStorageSystem(ev);
  509.     
  510.         _fDragItemList = new LinkedList;
  511.  
  512.         AEEventHandlerUPP theHandlerUPP = NewAEEventHandlerProc( ReplaceFileAEHandler ) ;
  513.         THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  514.                 kODReplaceFileEventID, theHandlerUPP, nil, false));
  515.     }
  516.  
  517. SOM_CATCH_ALL
  518.  
  519.     _fWindowState = kODNULL;
  520.     _fStorageSystem = kODNULL;
  521.     if (_fDragItemList)
  522.     {
  523.         delete _fDragItemList;
  524.         _fDragItemList = kODNULL;
  525.     }
  526.     if (_fReceiveHandler)
  527.     {
  528.         RemoveReceiveHandler(_fReceiveHandler, NULL);
  529.         DisposeRoutineDescriptor(_fReceiveHandler);
  530.         _fReceiveHandler = kODNULL;
  531.     }
  532.     if (_fTrackingHandler)
  533.     {
  534.         RemoveTrackingHandler(_fTrackingHandler, NULL);
  535.         DisposeRoutineDescriptor(_fTrackingHandler);
  536.         _fTrackingHandler = kODNULL;
  537.     }
  538.     if (_fSendDataHandler)
  539.     {
  540.         DisposeRoutineDescriptor(_fSendDataHandler);
  541.         _fSendDataHandler = kODNULL;
  542.     }
  543.  
  544. SOM_ENDTRY
  545. }
  546.  
  547. SOM_Scope ODULong  SOMLINK ODDragAndDropGetDragAttributes(ODDragAndDrop *somSelf, Environment *ev)
  548. {
  549.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  550.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragAttributes");
  551.  
  552.     if (_fTrackingHandler == kODNULL)
  553.         ODSetSOMException(ev, kODErrNoDragManager);
  554.  
  555.     return _fAttributes;
  556. }
  557.  
  558. SOM_Scope ODPlatformDragReference  SOMLINK ODDragAndDropGetDragReference(ODDragAndDrop *somSelf, Environment *ev)
  559. {
  560.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  561.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragReference");
  562.  
  563.     if (_fTrackingHandler == kODNULL)
  564.         ODSetSOMException(ev, kODErrNoDragManager);
  565.         
  566.     return _fDragReference;
  567. }
  568.  
  569.  
  570. SOM_Scope ODFacet*  SOMLINK ODDragAndDropFindTargetFacet(ODDragAndDrop *somSelf, Environment *ev,
  571.         ODPlatformWindow theWindow,
  572.         ODPoint* mouse,
  573.         ODPoint* localMouse)
  574. {
  575.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  576.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropFindTargetFacet");
  577.  
  578.     ODFacet   *targetFacet = kODNULL;
  579.     
  580.     if (_fTrackingHandler == kODNULL)
  581.         ODSetSOMException(ev, kODErrNoDragManager);
  582.     else {
  583.         SOM_TRY
  584.             ODFacet   *curFacet;
  585.             GrafPtr        curPort;
  586.             Point        qdLocal;
  587.             
  588.             {    TempODWindow targetWindow = _fWindowState->AcquireODWindow(ev,theWindow);
  589.                 if (!targetWindow)
  590.                     return kODNULL;
  591.             
  592.                 GetPort(&curPort);
  593.                 SetPort(theWindow);
  594.                 qdLocal = mouse->AsQDPoint();
  595.                 GlobalToLocal(&qdLocal);
  596.                 *localMouse = qdLocal;
  597.                 
  598.                 SetPort(curPort);
  599.             
  600.                 curFacet = targetWindow->GetFacetUnderPointForDrag(ev,
  601.                         localMouse);
  602.             }
  603.             
  604.             while (curFacet && !targetFacet)
  605.             {
  606.                 ODFrame* curFrame = curFacet->GetFrame(ev);
  607.                 #if ODDebug
  608.                     ODBoolean sample = kODFalse;
  609.                     sample = curFrame->IsDragging(ev);
  610.                     sample = curFrame->IsDroppable(ev);
  611.                     sample = curFrame->IsFrozen(ev);
  612.                     sample = IsNestedSelfEmbedding( somSelf, ev, curFrame );
  613.                     sample = _fFacetsRejected->Exists(&curFacet);
  614.                 #endif
  615.                 if (!curFrame->IsDragging(ev) &&
  616.                     curFrame->IsDroppable(ev) &&
  617.                     !curFrame->IsFrozen(ev) &&
  618.                     !IsNestedSelfEmbedding( somSelf, ev, curFrame ) &&
  619.                     !_fFacetsRejected->Exists(&curFacet))
  620.                 {
  621.                     targetFacet = curFacet;
  622.                 }
  623.                 curFacet = curFacet->GetContainingFacet(ev);
  624.             }
  625.             
  626.         SOM_CATCH_ALL
  627.         SOM_ENDTRY
  628.     }
  629.     return targetFacet;
  630. }
  631.  
  632. ODBoolean IsNestedSelfEmbedding( ODDragAndDrop *somSelf, Environment *ev, ODFrame* destFrame )
  633. {
  634. // Source frame: Frame that initiated the drag.
  635. // Destination frame: The frame where the drop will go. 
  636. // Indirect parent frame: A frame which is the parent of one of the parent's of an embedded
  637. // frame. It can be anywhere in the hierarchy of embedded frames above the embedded frame
  638. // in question.
  639. // Direct Embedded frame: An embedded frame whose containing frame is the source frame.
  640. // Nested embedded frame: An embedded frame whose indirect parent frame is embedded in the source frame.
  641.  
  642. // Want to check whether a drop destination is going to be in a nested embedded frame.
  643. // This will produce an infinite recursive situation when cloning.
  644.  
  645. // Note: We only need to check for nested self embedding, since single self embedding is already
  646. // covered by the IsDragging flag.
  647.  
  648. // Algorithm to check for self-embedding.
  649. //    1. Check if the destination frame's containing frame's IsDragging bit is set.
  650. //        A. If so return true. This is nested self-embedding.
  651. //    2. Set the current frame to the containing frame of the destination frame.
  652. //    3. If not, continue this iteration:
  653. //        A. Get the parent of the current frame and make it the current frame.
  654. //      B. If the current frame's IsDragging bit is set, return true.
  655. //        C. If the the current frame is null, return false. 
  656. //        D. If the the current frame == the source frame, return false. This means the frame was moved in the parent frame.
  657.  
  658.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  659.     ODBoolean loopDone = kODFalse;
  660.     ODBoolean selfEmbedding = kODFalse;
  661.     ODFrame* frameToBeReleased = kODNULL;
  662.  
  663.     ODFrame* sourceFrame = somThis->fSourceFrame;
  664.  
  665.     TRY
  666.         ODFrame* curFrame = destFrame->AcquireContainingFrame(ev);
  667.  
  668.         if( curFrame == kODNULL )
  669.         {
  670.             selfEmbedding = kODFalse;
  671.             loopDone = kODTrue;
  672.         }
  673.         else if( curFrame == sourceFrame )
  674.         {
  675.             selfEmbedding = kODFalse;
  676.             loopDone = kODTrue;
  677.         }
  678.         else if( curFrame->IsDragging(ev) == kODTrue)
  679.         {    
  680.             selfEmbedding = kODTrue;
  681.             loopDone = kODTrue;
  682.         }
  683.         frameToBeReleased = curFrame;
  684.         
  685.         while( !loopDone )
  686.         {
  687.             curFrame = curFrame->AcquireContainingFrame(ev); 
  688.             ODSafeReleaseObject( frameToBeReleased );
  689.             frameToBeReleased = curFrame;
  690.             if( curFrame == kODNULL )
  691.             {
  692.                 selfEmbedding = kODFalse;
  693.                 loopDone = kODTrue;
  694.             }
  695.             else if( curFrame == sourceFrame )
  696.             {
  697.                 selfEmbedding = kODFalse;
  698.                 loopDone = kODTrue;
  699.             }
  700.             else if( curFrame->IsDragging(ev) == kODTrue)
  701.             {    
  702.                 selfEmbedding = kODTrue;
  703.                 loopDone = kODTrue;
  704.             }
  705.         }
  706.     CATCH_ALL
  707.     ENDTRY
  708.     ODSafeReleaseObject( frameToBeReleased );
  709.     
  710.     return selfEmbedding;
  711. }
  712.  
  713. SOM_Scope void  SOMLINK ODDragAndDropGetPromiseFromDragManager(ODDragAndDrop *somSelf, Environment *ev,
  714.         ODPart* sourcePart,
  715.         ODStorageUnitView* destSUView)
  716. {
  717.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  718.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPromiseFromDragManager");
  719.  
  720.     SOM_TRY
  721.     
  722.     if (_fTrackingHandler == kODNULL)
  723.         THROW(kODErrNoDragManager);
  724.  
  725.     OSErr            err;
  726.     
  727.     if (sourcePart != kODNULL) {
  728.  
  729.         ItemReference    dragItemRef;
  730.         err = GetDragItemReferenceNumber(_fDragReference, 1, &dragItemRef);
  731.         ASSERTM(err == noErr, err, "Cannot get drag item reference in GetPromiseFromDragManager");
  732.  
  733.         ODPromiseDesc    theInfo;
  734.         theInfo.sourcePart = sourcePart;
  735.         theInfo.destSUView = destSUView;
  736.         
  737.         // Set the offset of the suview to the beginning of the value
  738.         destSUView->SetOffset(ev, 0);
  739.                 
  740.         AEDesc            dropLocation;
  741.         err = AECreateDesc(kODPromiseDesc, (Ptr) &theInfo, sizeof(theInfo), &dropLocation);
  742.         ASSERTM(err == noErr, err, "Error from AECreateDesc in GetPromiseFromDragManager");
  743.     
  744.         err = SetDropLocation(_fDragReference, &dropLocation);
  745.         ASSERTM(err == noErr, err, "Error from SetDropLocation in GetPromiseFromDragManager");
  746.  
  747.         gIsResolvingPromise = kODTrue;
  748.  
  749.         long            resolveResult;
  750.         Size            resolveSize = sizeof(long);
  751.         
  752.         err = GetFlavorData(_fDragReference, dragItemRef, kODPromiseFlavor, &resolveResult, &resolveSize, 0);
  753.         ASSERTM(err == cantGetFlavorErr, err, "Cannot GetFlavorData in GetPromiseFromDragManager");
  754.         
  755.         AEDisposeDesc(&dropLocation);
  756.     
  757.         // Reset the Drop location.
  758.  
  759.         gIsResolvingPromise = kODFalse;
  760.         
  761.         theInfo.sourcePart = kODNULL;
  762.         theInfo.destSUView = kODNULL;
  763.         
  764.         err = AECreateDesc(kODPromiseDesc, (Ptr) &theInfo, 0, &dropLocation);
  765.         ASSERTM(err == noErr, err, "Error from AECreateDesc in GetPromiseFromDragManager");
  766.         
  767.         err = SetDropLocation(_fDragReference, &dropLocation);
  768.         ASSERTM(err == noErr, err, "Error from SetDropLocation in GetPromiseFromDragManager");
  769.         
  770.         AEDisposeDesc(&dropLocation);
  771.     }
  772.     else {
  773.         ODHandle dataHandle = kODNULL;
  774.         ODType isoType = kODNULL;
  775.         TRY
  776.         
  777.             ODTranslation*    translate  = _fSession->GetTranslation(ev);
  778.             isoType = destSUView->GetType(ev);
  779.             if (ODISOStrNCompare((ODISOStr) isoType,(ODISOStr) kODAppleFileTypePrefix, ODISOStrLength(kODAppleFileTypePrefix)) != 0) {
  780.                 ItemReference   theItem;
  781.                 OSErr result;
  782.                 destSUView->SetOffset(ev,0);
  783.                 StorageUnitViewGetValue(destSUView, ev, sizeof(ItemReference), &theItem);            
  784.                 ODPlatformType platformType = translate->GetPlatformTypeFromISOType(ev, isoType);            
  785.                 if ( platformType == kODScrapTypestxt && !DragItemHasFlavor(_fDragReference, theItem, kODScrapTypestxt) )
  786.                 {
  787.                     // Create styled text from 'styl' and 'TEXT' flavors
  788. #ifdef ODDebug_DragAndDrop
  789.                     somPrintf("GetPromiseFromDragManager: Creating 'stxt' from 'styl' and 'TEXT'\n");
  790. #endif
  791.                     destSUView->SetOffset(ev,0);
  792.                     result = CopyFromDragItemInChunks(ev, kODScrapTypestyl, theItem, _fDragReference, destSUView);
  793.                     destSUView->SetOffset(ev, destSUView->GetSize(ev));
  794.                     result = CopyFromDragItemInChunks(ev, kODScrapTypeTEXT, theItem, _fDragReference, destSUView);
  795.                 }
  796.                 else
  797.                 {        
  798.                     destSUView->SetOffset(ev,0);
  799.                     result = CopyFromDragItemInChunks(ev, platformType, theItem, _fDragReference, destSUView);
  800.                 }
  801.             }
  802.             ODDisposePtr(isoType);
  803.         
  804.         CATCH_ALL
  805.         
  806.             if (dataHandle)
  807.                 ODDisposeHandle(dataHandle);
  808.             if (isoType)
  809.                 ODDisposePtr(isoType);
  810.             RERAISE;
  811.         
  812.         ENDTRY
  813.     }
  814.     
  815.     SOM_CATCH_ALL
  816.     SOM_ENDTRY
  817. }
  818.  
  819. SOM_Scope void  SOMLINK ODDragAndDropGetDataFromDragManager(ODDragAndDrop *somSelf, Environment *ev,
  820.         ODStorageUnitView*    suView)
  821. {
  822.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  823.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDataFromDragManager");
  824.     
  825.     WARN("ODDragAndDropGetDataFromDragManager is obsoleted.\n");
  826. }
  827.  
  828. SOM_Scope void  SOMLINK ODDragAndDropsomUninit(ODDragAndDrop *somSelf)
  829. {
  830.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  831.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropsomUninit");
  832.  
  833.     Environment* ev = somGetGlobalEnvironment();
  834.     somSelf->Clear(ev);
  835.         
  836.     if (_fDragItemList)
  837.     {
  838. //        _fDragItemList->DeleteAllLinks();
  839.         delete _fDragItemList;
  840.     }
  841. //    if (_fDragItemIterator)
  842. //        delete _fDragItemIterator;
  843.     if (_fReceiveHandler)
  844.     {
  845.         RemoveReceiveHandler(_fReceiveHandler, NULL);
  846.         DisposeRoutineDescriptor(_fReceiveHandler);
  847.     }
  848.     if (_fTrackingHandler)
  849.     {
  850.         RemoveTrackingHandler(_fTrackingHandler, NULL);
  851.         DisposeRoutineDescriptor(_fTrackingHandler);
  852.     }
  853.     if (_fSendDataHandler)
  854.     {
  855.         DisposeRoutineDescriptor(_fSendDataHandler);
  856.     }
  857.     
  858.     ODDeleteObject(_fFacetsRejected);
  859.     
  860.     ODDisposePtr(_fPSN);
  861.     ODDisposePtr(_fReplaceFileEvent);
  862. }
  863.  
  864. SOM_Scope void  SOMLINK ODDragAndDropClear(ODDragAndDrop *somSelf, Environment *ev)
  865. {
  866.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  867.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropClear");
  868.  
  869. #if ODDebug_DragAndDrop
  870.     somPrintf("In Clear\n");
  871. #endif
  872.  
  873.     SOM_TRY
  874.         if (_fTrackingHandler == kODNULL)
  875.             ODSetSOMException(ev, kODErrNoDragManager);
  876.         else
  877.         {
  878.             if (_fDragItemIterator)
  879.             {
  880.                 delete _fDragItemIterator;
  881.                 _fDragItemIterator = kODNULL;
  882.             }
  883.             _fDragItemList->DeleteAllLinks();
  884.         }
  885.  
  886.         int refCnt = 0;
  887.         if( _fMemItemContainer != kODNULL )
  888.         {
  889.             // Release temp in-memory container holding SU's for non-Bento files dragged in:
  890.             ODByteArray ba = _fMemItemContainer->GetID(ev);    // Get storage handle from container ID.
  891.             WASSERT(ba._length==sizeof(ODHandle));
  892.             
  893.             if( _fCachedMemContainerDraft != kODNULL )
  894.             {
  895.                 ODSafeReleaseObject( _fCachedMemContainerDraft );    // Undoes Acquire in EnterHandler.
  896.                 _fCachedMemContainerDraft = kODNULL;
  897.             }
  898.             
  899.             ODDocument* doc = _fMemItemContainer->AcquireDocument(ev, kODDefaultDocument);
  900.             if( doc != kODNULL )
  901.             {
  902.                 WASSERT(( refCnt = doc->GetRefCount(ev) )==2);
  903.                 ODSafeReleaseObject( doc );     // Undoes our Acquire.
  904.                 ODSafeReleaseObject( doc );        // Undoes Acquire in EnterHandler.
  905.             }
  906.             WASSERT( (refCnt = _fMemItemContainer->GetRefCount(ev) )==1);
  907.             ODSafeReleaseObject(_fMemItemContainer);
  908.             _fMemItemContainer = kODNULL;
  909.  
  910.             ODDisposeHandle( *(ODHandle*)ba._buffer);        // Finally dispose storage handle.
  911.             delete ba._buffer;
  912.             
  913.         }
  914.     SOM_CATCH_ALL
  915.         // The clear method is a notification that parts are required to call as part of the drag and drop
  916.         // protocal. Parts are not concerned with what this method does, or even if it succeeds. Calling this
  917.         // method is its sole responsibility for the protocal, and does not have to respond to any problems.
  918.         // Therefor, don't propogate any exceptions to the part. 
  919.         ODSetSOMException(ev, kODNoError);
  920.     SOM_ENDTRY
  921.  
  922. }
  923.  
  924. SOM_Scope ODStorageUnit*  SOMLINK ODDragAndDropGetContentStorageUnit(ODDragAndDrop *somSelf, Environment *ev)
  925. {
  926.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  927.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetContentStorageUnit");
  928.  
  929.     ODStorageUnit* contentSU = kODNULL;
  930.     
  931.     if (_fTrackingHandler == kODNULL)
  932.         ODSetSOMException(ev, kODErrNoDragManager);
  933.     else {
  934.         SOM_TRY
  935.  
  936.             ODMemDragItem    *newItem;
  937.             ODDragLink        *newLink;
  938.         
  939.             if( _fMemItemContainer == kODNULL ) {
  940.                 ODHandle memContainerHandle = ODNewHandle(0);
  941.                 _fMemItemContainer = CreateMemoryContainer(ev, _fSession,
  942.                                         memContainerHandle, kODBentoMemoryContainer);
  943. //                _fMemItemContainer->Acquire(ev);
  944.                 ODDocument* theDocument = _fMemItemContainer->AcquireDocument( ev, kODDefaultDocument );    
  945.                 _fCachedMemContainerDraft = theDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  946.                 // Refs to container/doc/draft will be released in Clear method.
  947.             }
  948.             newItem = new(ODGetDefaultHeap()) ODMemDragItem(_fStorageSystem, _fCachedMemContainerDraft, kODFalse, 0, 0, kODNULL);
  949.             ASSERTM(newItem != kODNULL, kODErrCannotAllocateDragItem, "Error allocating drag item");
  950.             newItem->Initialize(ev);
  951.             newLink = new ODDragLink(newItem, kODTrue);
  952.             if (!newLink)
  953.             {
  954.                 delete newItem;
  955.                 ASSERTM(newLink != kODNULL, kODErrCannotAllocateDragItem, "Error allocating drag link");
  956.             }
  957.             _fDragItemList->AddLast(newLink);
  958.             contentSU = newItem->GetStorageUnit(ev);
  959.             
  960.         SOM_CATCH_ALL
  961.         SOM_ENDTRY
  962.     }
  963.     return contentSU;
  964. }
  965.  
  966. SOM_Scope ODDropResult  SOMLINK ODDragAndDropStartDrag(ODDragAndDrop *somSelf, Environment *ev,
  967.         ODFrame* srcFrame,
  968.         ODType imageType,
  969.         ODByteArray* image,
  970.         ODPart** destPart,
  971.         ODByteArray* refCon)
  972. {
  973.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  974.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropStartDrag");
  975.  
  976.     LinkedListIterator *theIter = kODNULL;    ODVolatile(theIter);
  977.  
  978. SOM_TRY
  979.     if (_fTrackingHandler == kODNULL)
  980.         THROW(kODErrNoDragManager);
  981.  
  982.     ASSERT(image != kODNULL, kODErrIllegalNullInput);
  983.     ASSERT(refCon != kODNULL, kODErrIllegalNullInput);
  984.  
  985.     OSErr               result;
  986.     RgnHandle           imageRgn;
  987.     ODTranslation     *translate;
  988.     ODULong            count, index;
  989.     ODType             theISOType;
  990.     ODPlatformType     platformType;
  991.     PromiseHFSFlavor    thePromise;
  992.     ODStorageUnit     *theSU;
  993.     ODDragLink        *theDragLink;
  994.  
  995.     // Check if we know what the image type is
  996.     ASSERTM(ODISOStrEqual(imageType, kODDragImageRegionHandle), kODErrUnknownDragImageType, "Unknown image type in StartDrag");
  997.  
  998.     // Set the drop result to kODDropFail. - VL
  999.     _fDropResult = kODDropFail;
  1000.     
  1001.     // Begin the drag by creating a new drag reference
  1002.     result = NewDrag(&_fDragReference);
  1003.     ASSERTM(result == noErr, result, "Bad result from NewDrag");
  1004.     
  1005. #ifdef ODDebug_DragAndDrop
  1006. //    PrintDragReference(_fDragReference, "After NewDrag");
  1007. #endif
  1008.  
  1009.     // Register a send procedure so we don't have to cache any data with the drag manager
  1010.     result = SetDragSendProc(_fDragReference, _fSendDataHandler, (void *) somSelf);
  1011.     ASSERTM(result == noErr, result, "Bad result from SetDragSendProc");
  1012.  
  1013.     // Scan through all items in the drag and add a flavor for each value
  1014.     // in the storage unit's kODContents property
  1015.     theIter = new LinkedListIterator(_fDragItemList);
  1016.     translate = _fSession->GetTranslation(ev);
  1017.     imageRgn = *((RgnHandle*) image->_buffer);
  1018.     for (theDragLink = (ODDragLink*)theIter->First(); theDragLink; theDragLink = (ODDragLink*)theIter->Next())
  1019.     {
  1020.         theSU = theDragLink->fItem->GetStorageUnit(ev);
  1021.         ODBoolean    userPromise = ODSUExistsThenFocus(ev, theSU, kODPropContents, kODHFSPromise);
  1022.         if (userPromise)
  1023.         {
  1024.             ODByteArray ba;
  1025.             ODPart* dummySourcePart;
  1026.             theSU->GetPromiseValue(ev, kODHFSPromise, 0, sizeof(PromiseHFSFlavor), &ba, &dummySourcePart);
  1027.             if (ba._buffer)
  1028.             {
  1029.                 ODBlockMove(ba._buffer, &thePromise, ba._length);
  1030.                 ODDisposePtr(ba._buffer);
  1031.             }
  1032.             thePromise.promisedFlavor = kODUserPromiseFlavor;
  1033.         }
  1034.         else
  1035.         {
  1036.             // Always promise a file in case somebody wishes to drag this out to the finder
  1037.             thePromise.fileType = GetStorageUnitOSType(ev,theSU);
  1038.             thePromise.fileCreator = ODGetIconFilePlatformCreatorFromPartSU(ev,theSU);
  1039.             thePromise.fdFlags = 0;
  1040.             thePromise.promisedFlavor = kODBentoFlavor;
  1041.         }
  1042.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), flavorTypePromiseHFS,
  1043.                                    &thePromise, sizeof(PromiseHFSFlavor), 0);
  1044.         ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1045.  
  1046.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), (userPromise ? kODUserPromiseFlavor : kODBentoFlavor), 0L, 0L, 0);
  1047.         ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1048.         
  1049.         result = SetDragItemBounds(_fDragReference, (ItemReference)(theDragLink->fItem), &((**imageRgn).rgnBBox));
  1050.         ASSERTM(result == noErr, result, "Bad result from SetDragItemBounds");
  1051.  
  1052. #ifdef ODDebug_DragAndDrop
  1053. //    PrintStorageUnit(ev, theSU, "DragItem SU");
  1054. #endif
  1055.         theSU->Focus(ev,kODPropContents, kODPosUndefined, 0, 0, kODPosUndefined);
  1056.         count = theSU->CountValues(ev);
  1057.         for (index = 1; index <= count; ++index)
  1058.         {
  1059.             theSU->Focus(ev,kODPropContents, kODPosUndefined, 0, index, kODPosUndefined);
  1060.             theISOType = theSU->GetType(ev);
  1061.             platformType = translate->GetPlatformTypeFromISOType(ev, theISOType);
  1062.             ODDisposePtr(theISOType);
  1063.             if (!platformType)
  1064.                 continue;
  1065.             result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), platformType, 0L, 0L, 0);
  1066.             ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1067.  
  1068.             // If styled text ('stxt') was just added, also add 'styl' if
  1069.             // a 'TEXT' representation will also be written.
  1070.             if (     (platformType == kODScrapTypestxt)
  1071.                   && theSU->Exists(ev, kODPropContents, kODAppleTEXT, 0)
  1072.                   && !theSU->Exists(ev, kODPropContents, kODApplestyl, 0) )
  1073.             {
  1074.                 result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), kODScrapTypestyl, 0L, 0L, 0);
  1075.                 ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1076.             }
  1077.         }
  1078.     
  1079.         // Always add our special dummy promise to the drag
  1080.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), kODPromiseFlavor, 0L, 0L, 0);
  1081.         ASSERTM(result == noErr, result, "Bad result from adding kODPromiseFlavor");
  1082.     }
  1083.  
  1084.     _fSourceFrame = srcFrame;
  1085.     _fSourcePart = srcFrame->AcquirePart(ev);
  1086.  
  1087.     TRY
  1088.         TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1089.         
  1090.         _fDestFacet = kODNULL;
  1091.         _fDragItemIterator = new ODDragItemIterator();
  1092.         THROW_IF_NULL(_fDragItemIterator, kODErrOutOfMemory);
  1093.         _fDragItemIterator->InitDragItemIterator(ev, theIter);
  1094.         _fHasLeftSourceFrame = kODFalse;
  1095.         _fHasLeftSourcePart = kODFalse;
  1096.         
  1097.         #ifdef ODDebug_DragAndDrop
  1098.         //    PrintDragReference(_fDragReference, "Before TrackDrag");
  1099.         #endif
  1100.     
  1101.         // Do the drag    
  1102.         result = TrackDrag(_fDragReference, *((EventRecord**) refCon->_buffer), imageRgn);
  1103.  
  1104.         if( result != noErr )
  1105.             THROW( result );
  1106.         if (_fDestFacet)
  1107.             *destPart = _fDestFacet->GetFrame(ev)->AcquirePart(ev);
  1108.         else
  1109.             *destPart = kODNULL;
  1110.     CATCH_ALL
  1111.         DisposeDrag(_fDragReference);
  1112.         _fDragReference = kODNULL;
  1113.         ODSafeReleaseObject( _fSourcePart);
  1114.         _fSourcePart = kODNULL;
  1115.         RERAISE;
  1116.     ENDTRY
  1117.             
  1118.     DisposeDrag(_fDragReference);
  1119.     _fDragReference = kODNULL;
  1120. //    if( _fDragItemIterator != kODNULL )
  1121. //    {
  1122. //        delete _fDragItemIterator;
  1123. //        _fDragItemIterator = kODNULL;
  1124. //    }    
  1125.  
  1126.     _fSourceFrame = kODNULL;
  1127.     ODSafeReleaseObject( _fSourcePart );
  1128.     _fSourcePart = kODNULL;
  1129.     _fDestFacet = kODNULL;
  1130.     somSelf->Clear(ev);
  1131.  
  1132.     if (_fShouldSendReplaceFileEvent)
  1133.     {
  1134.         _fShouldSendReplaceFileEvent = kODFalse;
  1135.         OSErr err = SetupReplaceFileEvent(ev,
  1136.             _fReplaceFileEvent,
  1137.             &gTmpFileFSSpec,
  1138.             &gTargetFSSpec);
  1139.         SendReplaceFileEvent(_fReplaceFileEvent, _fPSN);
  1140.         DisposeReplaceFileEvent(_fReplaceFileEvent);
  1141.         CreateReplaceFileEvent(ev,
  1142.             _fReplaceFileEvent,
  1143.             _fSession,
  1144.             _fPSN);
  1145.     }
  1146.  
  1147. SOM_CATCH_ALL
  1148.  
  1149.     if( _fDragItemIterator != kODNULL )
  1150.     {
  1151.         delete _fDragItemIterator;
  1152.         _fDragItemIterator = kODNULL;
  1153.     }    
  1154.     somSelf->Clear(ev);
  1155.     if (_fDragReference)
  1156.         DisposeDrag(_fDragReference);
  1157.     _fDragReference = kODNULL;
  1158.     
  1159. SOM_ENDTRY
  1160.  
  1161.     if (_fDropResult == kODDropMove)
  1162.         return kODDropMove;
  1163.     else if (_fDropResult == kODDropCopy)
  1164.         return kODDropCopy;
  1165.     else
  1166.         return kODDropFail;
  1167. }
  1168.  
  1169.  
  1170. SOM_Scope LinkedList*  SOMLINK ODDragAndDropGetDragItemList(ODDragAndDrop *somSelf, Environment *ev)
  1171. {
  1172.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1173.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemList");
  1174.  
  1175.     return _fDragItemList;
  1176. }
  1177.  
  1178. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemList(ODDragAndDrop *somSelf, Environment *ev,
  1179.         LinkedList* list)
  1180. {
  1181.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1182.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemList");
  1183.  
  1184.     _fDragItemList = list;
  1185. }
  1186.  
  1187. SOM_Scope ODBoolean  SOMLINK ODDragAndDropGetListFromHandler(ODDragAndDrop *somSelf, Environment *ev)
  1188. {
  1189.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1190.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetListFromHandler");
  1191.  
  1192.     return _fListFromHandler;
  1193. }
  1194.  
  1195. SOM_Scope void  SOMLINK ODDragAndDropSetListFromHandler(ODDragAndDrop *somSelf, Environment *ev,
  1196.         ODBoolean listFromHandler)
  1197. {
  1198.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1199.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetListFromHandler");
  1200.  
  1201.     _fListFromHandler = listFromHandler;
  1202. }
  1203.  
  1204. SOM_Scope ODFrame*  SOMLINK ODDragAndDropGetSourceFrame(ODDragAndDrop *somSelf, Environment *ev)
  1205. {
  1206.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1207.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourceFrame");
  1208.  
  1209.     return _fSourceFrame;
  1210. }
  1211.  
  1212. SOM_Scope void  SOMLINK ODDragAndDropSetSourceFrame(ODDragAndDrop *somSelf, Environment *ev,
  1213.         ODFrame* sourceFrame)
  1214. {
  1215.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1216.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourceFrame");
  1217.  
  1218.     _fSourceFrame = sourceFrame;
  1219. }
  1220.  
  1221. SOM_Scope ODULong  SOMLINK ODDragAndDropGetAttributes(ODDragAndDrop *somSelf, Environment *ev)
  1222. {
  1223.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1224.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetAttributes");
  1225.  
  1226.     return _fAttributes;
  1227. }
  1228.  
  1229. SOM_Scope void  SOMLINK ODDragAndDropSetAttributes(ODDragAndDrop *somSelf, Environment *ev,
  1230.         ODULong attr)
  1231. {
  1232.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1233.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetAttributes");
  1234.  
  1235.     _fAttributes = attr;
  1236. }
  1237.  
  1238. SOM_Scope ODPart*  SOMLINK ODDragAndDropGetSourcePart(ODDragAndDrop *somSelf, Environment *ev)
  1239. {
  1240.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1241.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourcePart");
  1242.  
  1243.     return _fSourcePart;
  1244. }
  1245.  
  1246. SOM_Scope void  SOMLINK ODDragAndDropSetSourcePart(ODDragAndDrop *somSelf, Environment *ev,
  1247.         ODPart* sourcePart)
  1248. {
  1249.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1250.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourcePart");
  1251.  
  1252.     _fSourcePart = sourcePart;
  1253. }
  1254.  
  1255. SOM_Scope ODDragItemIterator*  SOMLINK ODDragAndDropGetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev)
  1256. {
  1257.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1258.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemIterator");
  1259.  
  1260.     return _fDragItemIterator;
  1261. }
  1262.  
  1263. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev,
  1264.         ODDragItemIterator* iter)
  1265. {
  1266.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1267.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemIterator");
  1268.  
  1269.     _fDragItemIterator = iter;
  1270. }
  1271.  
  1272. SOM_Scope ODSession*  SOMLINK ODDragAndDropGetSession(ODDragAndDrop *somSelf, Environment *ev)
  1273. {
  1274.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1275.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSession");
  1276.  
  1277.     return _fSession;
  1278. }
  1279.  
  1280. SOM_Scope ODStorageSystem*  SOMLINK ODDragAndDropGetStorageSystem(ODDragAndDrop *somSelf, Environment *ev)
  1281. {
  1282.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1283.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetStorageSystem");
  1284.  
  1285.     return _fStorageSystem;
  1286. }
  1287.  
  1288. SOM_Scope void  SOMLINK ODDragAndDropSetDragReference(ODDragAndDrop *somSelf, Environment *ev,
  1289.         ODPlatformDragReference dragReference)
  1290. {
  1291.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1292.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragReference");
  1293.     
  1294.     _fDragReference = dragReference;
  1295. }
  1296.  
  1297. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetPrevFacet(ODDragAndDrop *somSelf, Environment *ev)
  1298. {
  1299.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1300.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPrevFacet");
  1301.  
  1302.     return _fPrevFacet;
  1303. }
  1304.  
  1305. SOM_Scope void  SOMLINK ODDragAndDropSetPrevFacet(ODDragAndDrop *somSelf, Environment *ev,
  1306.         ODFacet* prevFacet)
  1307. {
  1308.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1309.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetPrevFacet");
  1310.  
  1311.     _fPrevFacet = prevFacet;
  1312. }
  1313.  
  1314. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetDestFacet(ODDragAndDrop *somSelf, Environment *ev)
  1315. {
  1316.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1317.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDestFacet");
  1318.  
  1319.     return _fDestFacet;
  1320. }
  1321.  
  1322. SOM_Scope void  SOMLINK ODDragAndDropSetDestFacet(ODDragAndDrop *somSelf, Environment *ev,
  1323.         ODFacet* destFacet)
  1324. {
  1325.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1326.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDestFacet");
  1327.  
  1328.     _fDestFacet = destFacet;
  1329. }
  1330.  
  1331. SOM_Scope ODDropResult  SOMLINK ODDragAndDropGetDropResult(ODDragAndDrop *somSelf, Environment *ev)
  1332. {
  1333.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1334.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1335.  
  1336.     return _fDropResult;
  1337. }
  1338.  
  1339. SOM_Scope void  SOMLINK ODDragAndDropSetDropResult(ODDragAndDrop *somSelf, Environment *ev,
  1340.         ODDropResult dropResult)
  1341. {
  1342.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1343.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDropResult");
  1344.  
  1345.     _fDropResult = dropResult;
  1346. }
  1347.  
  1348. SOM_Scope ProcessSerialNumber*   SOMLINK ODDragAndDropGetPSN(ODDragAndDrop *somSelf, Environment *ev)
  1349. {
  1350.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1351.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1352.  
  1353.     return _fPSN;
  1354. }
  1355.  
  1356. SOM_Scope AppleEvent*   SOMLINK ODDragAndDropGetReplaceFileEvent(ODDragAndDrop *somSelf, Environment *ev)
  1357. {
  1358.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1359.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1360.  
  1361.     return _fReplaceFileEvent;
  1362. }
  1363.  
  1364. SOM_Scope void   SOMLINK ODDragAndDropSetShouldSendReplaceFileEvent(ODDragAndDrop *somSelf, Environment *ev,
  1365.     ODBoolean shouldSend)
  1366. {
  1367.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1368.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1369.  
  1370.     _fShouldSendReplaceFileEvent = shouldSend;
  1371. }
  1372.  
  1373. pascal OSErr MyDragTrackingHandler(
  1374.         short message,
  1375.         WindowPtr theWindow,
  1376.         void* handlerRefCon,
  1377.         ODPlatformDragReference theDrag)
  1378. {
  1379.     ODDragAndDrop  *self = (ODDragAndDrop*)handlerRefCon;
  1380.     ODPoint            mouse, localMouse;
  1381.     OSErr            returnCode = noErr;
  1382.  
  1383.     TRY
  1384.         TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1385.     
  1386.         Environment*    ev = somGetGlobalEnvironment();
  1387.     
  1388.         switch (message)
  1389.         {
  1390.             case dragTrackingEnterHandler:
  1391.                 returnCode = self->EnterHandler(ev, theDrag);
  1392.                 break;            
  1393.             case dragTrackingEnterWindow:
  1394.                 returnCode = self->EnterWindow(ev, theDrag, theWindow);
  1395.                 break;
  1396.  
  1397.             case dragTrackingInWindow:
  1398.                 returnCode = self->InWindow(ev, theDrag, theWindow);
  1399.                 break;
  1400.                 
  1401.             case dragTrackingLeaveWindow:
  1402.                 returnCode = self->LeaveWindow(ev, theDrag, theWindow);
  1403.                 break;
  1404.                 
  1405.             case dragTrackingLeaveHandler:
  1406.                 returnCode = self->LeaveHandler(ev);
  1407.                 break;
  1408.         }
  1409.     
  1410.     CATCH_ALL
  1411.     
  1412.         returnCode = ErrorCode();
  1413.     
  1414.     ENDTRY
  1415.  
  1416.     return returnCode;
  1417. }
  1418.  
  1419. pascal OSErr    MyReceiveDropHandler(
  1420.         WindowPtr theWindow,
  1421.         void* handlerRefCon,
  1422.         ODPlatformDragReference theDrag)
  1423. {
  1424.     ODDragAndDrop    *self = (ODDragAndDrop*)handlerRefCon;
  1425.     ODPoint            mouse, localMouse;
  1426.     Point            qdMouse;
  1427.     ODFacet            *targetFacet;
  1428.     OSErr            returnCode = noErr;
  1429.  
  1430. #ifdef ODDebug_DragAndDrop
  1431.     somPrintf("MyReceiveDropHandler\n");
  1432. #endif
  1433.  
  1434.     Environment* ev = somGetGlobalEnvironment();
  1435.  
  1436.     TRY
  1437.     TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1438.  
  1439.     GetDragMouse(theDrag, &qdMouse, 0L);
  1440.     mouse = qdMouse;
  1441.     targetFacet = self->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  1442.         
  1443.     if (!targetFacet || !(self->GetDragItemList(ev)->Count()))
  1444.         returnCode = dragNotAcceptedErr;
  1445.     else
  1446.     {
  1447.         TempODPart targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  1448.  
  1449.         // Assume _fDropResult is kODDropMove
  1450.         
  1451.         self->SetDropResult(ev, kODDropMove);
  1452.         
  1453.         // Are we going across Drafts?
  1454.         
  1455.         ODPart* sourcePart = self->GetSourcePart(ev);
  1456.         if ((sourcePart == kODNULL) || 
  1457.             (targetPart->GetStorageUnit(ev)->GetDraft(ev) != 
  1458.             sourcePart->GetStorageUnit(ev)->GetDraft(ev)))
  1459.             self->SetDropResult(ev, kODDropCopy);
  1460.  
  1461.         ODSShort    mouseDownModifiers;
  1462.         ODSShort    mouseUpModifiers;
  1463.                 
  1464.         GetDragModifiers(self->GetDragReference(ev), 0L, &mouseDownModifiers, &mouseUpModifiers);
  1465.  
  1466.         // Check the mandatory modifier keys first
  1467.         
  1468.         if (mouseUpModifiers & optionKey) {
  1469.             self->SetDropResult(ev, kODDropCopy);
  1470.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1471.         }
  1472.         else if (mouseUpModifiers & controlKey) {
  1473.             self->SetDropResult(ev, kODDropMove);
  1474.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1475.         }
  1476.         else if (mouseUpModifiers & cmdKey) {
  1477.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1478.         }
  1479.  
  1480.         // Then check the optional modifier keys
  1481.         
  1482.         else if (mouseDownModifiers & optionKey) {
  1483.             self->SetDropResult(ev, kODDropCopy);
  1484.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1485.         }
  1486.         else if (mouseDownModifiers & controlKey) {
  1487.             self->SetDropResult(ev, kODDropMove);
  1488.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1489.         }
  1490.         else if (mouseDownModifiers & cmdKey) {
  1491.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1492.         }
  1493.                     
  1494.         // Check to see whether it is an override by source part.
  1495.         ODDragItemIterator* dragItemIter = self->GetDragItemIterator(ev);
  1496.         if (dragItemIter)
  1497.         {
  1498.             ODStorageUnit* su = dragItemIter->First(ev);
  1499.             ODDraft* draft = su->GetDraft(ev);
  1500.             ODCloneKind cloneKind = GetOriginalCloneKind(ev, draft);
  1501.             if (cloneKind == kODCloneCopy)
  1502.                 self->SetDropResult(ev, kODDropCopy);
  1503.         }
  1504.         
  1505.         // Drop
  1506. #ifdef ODDebug_DragAndDrop
  1507.     somPrintf("Calling Drop on targetFacet %x\n", targetFacet);
  1508. #endif
  1509.  
  1510.         self->SetAttributes(ev, self->GetAttributes(ev) | 
  1511.                 (self->GetDropResult(ev) == kODDropMove ? kODDropIsMove : kODDropIsCopy));
  1512.                 
  1513.         if (targetFacet->GetFrame(ev) == self->GetSourceFrame(ev))
  1514.             self->SetAttributes(ev, self->GetAttributes(ev) | (kODDropIsInSourceFrame | kODDropIsInSourcePart));
  1515.         else if (targetPart == self->GetSourcePart(ev))
  1516.             self->SetAttributes(ev, self->GetAttributes(ev) | kODDropIsInSourcePart);
  1517.                 
  1518.         self->SetDestFacet(ev, targetFacet);
  1519.         self->SetPrevFacet(ev, kODNULL);
  1520.         ODULong dropResult; ODVolatile(dropResult);
  1521.         SOM_TRY
  1522.              dropResult= targetFacet->Drop(ev, &localMouse, self->GetDragItemIterator(ev), kODNULL);
  1523.         SOM_CATCH_ALL
  1524.         SOM_ENDTRY
  1525.         if (dropResult == kODDropFail) {
  1526.             self->SetDropResult(ev, dropResult);
  1527.             returnCode = dragNotAcceptedErr;
  1528. //            returnCode = ErrorCode();
  1529.         }
  1530.         else if ((self->GetDropResult(ev) == kODDropMove) && (dropResult == kODDropCopy)) {
  1531.             self->SetDropResult(ev, kODDropCopy);
  1532.             returnCode = noErr;
  1533.         }
  1534.         
  1535.         ODDragItemIterator* iter = self->GetDragItemIterator(ev);
  1536.         ODSession* destSession = self->GetSession(ev);
  1537.         for (ODStorageUnit* su = iter->First(ev); iter->IsNotComplete(ev); su = iter->Next(ev)) {
  1538.             ODSession* sourceSession = su->GetSession(ev);
  1539.             if ((sourceSession != kODNULL) && (sourceSession != destSession)) {
  1540.                 ODDragAndDrop* sourceDAD = sourceSession->GetDragAndDrop(ev);
  1541.                 if (sourceDAD != kODNULL) {
  1542.                     sourceDAD->SetDropResult(ev, self->GetDropResult(ev));
  1543.                     sourceDAD->SetDestFacet(ev, targetFacet);
  1544.                 }
  1545.             }
  1546.         }
  1547.     }
  1548.  
  1549.     CATCH_ALL
  1550.  
  1551.     self->SetDropResult(ev, kODDropFail);
  1552.     returnCode = dragNotAcceptedErr;
  1553. #if ODDebug            
  1554.     somPrintf("Error in MyReceiveDropHandler.\n");
  1555. #endif
  1556.  
  1557.     ENDTRY
  1558.  
  1559.     ODEventData    event;
  1560.     WaitNextEvent(mUpMask, (EventRecord*) &event, 0, kODNULL);
  1561. #if ODDebug_DragAndDrop            
  1562.     somPrintf("message %x when %x where %x modifier %x\n", event.message, event.when, event.where, event.modifiers);
  1563. #endif
  1564.  
  1565.     return returnCode;
  1566. }
  1567.  
  1568. pascal OSErr  MySendDataProc(
  1569.         FlavorType theType,
  1570.         void* refCon,
  1571.         ItemReference theItem,
  1572.         ODPlatformDragReference theDrag)
  1573. {
  1574.     ODDragAndDrop    *self = (ODDragAndDrop*)refCon;
  1575.     Environment*    ev = somGetGlobalEnvironment();
  1576.     OSErr            result = noErr;
  1577.     ODType            theISOType;
  1578.     ODTranslation    *translate;
  1579.     AEDesc            dropDescriptor;
  1580.     ODPtr            stylPtr = kODNULL;
  1581.     ODULong            stylSize = 0;
  1582.  
  1583.     ODVolatile(result);
  1584.     TRY
  1585.     
  1586.     TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1587.  
  1588.     LinkedListIterator iter(self->GetDragItemList(ev));
  1589.     ODDragLink*        theDragLink = kODNULL;
  1590.     ODMemDragItem*    theDragItem = kODNULL;
  1591.  
  1592. #ifdef ODDebug_DragAndDrop
  1593.     somPrintf("Entering MySendDataProc.\n");
  1594. #endif
  1595.  
  1596.     for (theDragLink = (ODDragLink*)iter.First(); 
  1597.          theDragLink; theDragLink = (ODDragLink*)iter.Next())
  1598.     {
  1599.         if (theDragLink->fItem == (ODDragItem*)theItem)
  1600.         {
  1601.             theDragItem = (ODMemDragItem*) theDragLink->fItem;
  1602.             break;
  1603.         }
  1604.     }
  1605.     if (!theDragItem)
  1606.     {
  1607.         WARN("Item not found in send proc");
  1608.         result =  badDragFlavorErr;
  1609.     }
  1610.     else {
  1611.         switch (theType)
  1612.         {
  1613.             case kODPromiseFlavor:
  1614. #ifdef ODDebug_DragAndDrop
  1615.     somPrintf("MySendDataProc: kODPromiseFlavor\n");
  1616. #endif
  1617.                 if (gIsResolvingPromise)
  1618.                 {
  1619.                     result = GetDropLocation(theDrag, &dropDescriptor);
  1620.                     if ((result != noErr) || (dropDescriptor.descriptorType != kODPromiseDesc)) {
  1621.                         WARN("Error from GetDropLocation in send procedure");
  1622.                     }
  1623.                     else {
  1624.                         ODPromiseDesc     theInfo;
  1625.                         ODBlockMove((Ptr)(*dropDescriptor.dataHandle), (Ptr)&theInfo, sizeof(ODPromiseDesc));
  1626.                         if (theInfo.sourcePart && theInfo.destSUView)
  1627.                         {
  1628.                             TRY
  1629.                                 theInfo.sourcePart->FulfillPromise(ev, theInfo.destSUView);
  1630.                             CATCH_ALL
  1631.                                 WARN("Error from FulfillPromise.");
  1632.                             ENDTRY
  1633.                         }
  1634.                     result = noErr;
  1635.                     }
  1636.                 }
  1637.             break;
  1638.             case kODUserPromiseFlavor:
  1639. #ifdef ODDebug_DragAndDrop
  1640.     somPrintf("MySendDataProc: kODUserPromiseFlavor\n");
  1641. #endif
  1642.                 result = noErr;
  1643.                 ODStorageUnit* contentSU = theDragItem->GetStorageUnit(ev);
  1644.                 if ((contentSU != kODNULL) && (contentSU->Exists(ev, kODPropContents, kODHFSPromise, 0)))
  1645.                 {
  1646.                     FSSpec dropFSSpec;
  1647.                     result = GetDropFSSpec(theDrag, dropFSSpec);
  1648.                     if (result == noErr)
  1649.                     {
  1650.                         TRY
  1651.                             contentSU->Focus(ev, kODPropContents, kODPosUndefined, kODHFSPromise, 0, kODPosUndefined);
  1652.                             StorageUnitSetPromiseValue(contentSU, ev, kODHFSPromise, 0, sizeof(FSSpec), &dropFSSpec, self->GetSourcePart(ev));
  1653.                             contentSU->Focus(ev, kODPropContents, kODPosUndefined, kODHFSPromise, 0, kODPosUndefined);
  1654.                             ODULong size = StorageUnitGetValue(contentSU, ev, sizeof(FSSpec), &dropFSSpec);
  1655.                             if (size != sizeof(FSSpec))
  1656.                             {
  1657.                                 self->SetDropResult(ev, kODDropFail);
  1658.                                 result = fnfErr;
  1659.                             }
  1660.                             else
  1661.                             {
  1662.                                 self->SetDropResult(ev, IsTrashFolder(dropFSSpec) ? kODDropMove : kODDropCopy);
  1663.                                 SetDragItemFlavorData(theDrag, theItem, theType, &dropFSSpec, sizeof(FSSpec), 0L);
  1664.                             }
  1665.                         CATCH_ALL
  1666.                             WARN("Error from FulfillPromise.");
  1667.                         ENDTRY
  1668.                     }
  1669.                     // If we get a file not found error, most likely we are trying to drag to somewhere other than the Finder.
  1670.                     // That's OK, so just eat the error.
  1671.                     if( result == fnfErr )
  1672.                         result = noErr;
  1673.                 }
  1674.             break;
  1675.             case kODBentoFlavor:
  1676.             {
  1677. #ifdef ODDebug_DragAndDrop
  1678.     somPrintf("MySendDataProc: kODBentoFlavor\n");
  1679. #endif
  1680.                 // Check the drop location (probably from the finder)
  1681.                 FSSpec dropFSSpec;
  1682.                 
  1683.                 result = GetDropFSSpec(theDrag, dropFSSpec);
  1684.                 if (result == noErr)
  1685.                 {
  1686.                     ODSShort    mouseDownModifiers;
  1687.                     ODSShort    mouseUpModifiers;
  1688.                                 
  1689.                     GetDragModifiers(self->GetDragReference(ev), 0L, &mouseDownModifiers, &mouseUpModifiers);
  1690.  
  1691.                     // Check the mandatory modifier keys first
  1692.                         
  1693.                     if (mouseUpModifiers & controlKey)
  1694.                         self->SetDropResult(ev, kODDropMove);    // Need to take care of moving to the Finder.
  1695.                     else
  1696.                         self->SetDropResult(ev, kODDropFail);    // Copied to non OpenDoc process, so return fail so part will
  1697.                                                                 // not post undo action.    
  1698.                     boolean nameFromPart = MakeUniqueFilename(ev, self->GetSession(ev), theDragItem->GetStorageUnit(ev), &dropFSSpec);
  1699.                     
  1700.                     // Drags to the Trash are always a move
  1701.                     boolean isDraggingToTrash = IsTrashFolder(dropFSSpec);
  1702.     
  1703.                     if (isDraggingToTrash)
  1704.                     {
  1705.                         self->SetDropResult(ev, kODDropMove);   // Dragged to Trash, so it's a move.
  1706.  
  1707.                         TempPlatformFile file = new PlatformFile;
  1708.                         file->Specify(&dropFSSpec);
  1709.     
  1710.                         if (file->Exists())
  1711.                         {
  1712.                             // If the target file exists in trash already,
  1713.                             // set the fsspec to the temp folder.
  1714.                             RespecifyToTempFolder(file);
  1715.                             
  1716.                             // Clone the data.
  1717.                             CloneIntoFile(ev, theDragItem, file->GetFileSpec());
  1718.                             
  1719.                             // After cloning the data to the file (in temp folder),
  1720.                             // move to it trash.
  1721.                             file->MoveToTrash();
  1722.                             
  1723.                             // Set the result for Drag Manager.
  1724.                             SetDragItemFlavorData(theDrag, theItem, theType, &(file->GetFileSpec()), sizeof(FSSpec), 0L);
  1725.                         }
  1726.                         else
  1727.                         {    
  1728.                             CloneIntoFlavor(ev, self, theDragItem,
  1729.                                             theDrag, theItem, theType,
  1730.                                             dropFSSpec);
  1731.                         }
  1732.                     }
  1733.                     else if (!nameFromPart)
  1734.                     {
  1735.                         CloneIntoFlavor(ev, self, theDragItem,
  1736.                                         theDrag, theItem, theType,
  1737.                                         dropFSSpec);
  1738.                     }
  1739.                     else if (IsFrontProcess())
  1740.                     {
  1741.                         TempPlatformFile file = new PlatformFile;
  1742.                         file->Specify(&dropFSSpec);
  1743.     
  1744.                         if (file->Exists())
  1745.                         {
  1746.                             ParamText(dropFSSpec.name, "\p", "\p", "\p");
  1747.                             if (ODAskUserReplace(ev, self->GetSession(ev)))
  1748.                             {                        
  1749.                                 file->MoveToTrash();
  1750.                                 CloneIntoFlavor(ev, self, theDragItem,
  1751.                                                 theDrag, theItem, theType,
  1752.                                                 dropFSSpec);
  1753.                             }
  1754.                         }
  1755.                         else
  1756.                         {
  1757.                             CloneIntoFlavor(ev, self, theDragItem,
  1758.                                             theDrag, theItem, theType,
  1759.                                             dropFSSpec);
  1760.                         }
  1761.                     }
  1762.                     else
  1763.                     {
  1764.                         TempPlatformFile file = new PlatformFile;
  1765.                         file->Specify(&dropFSSpec);
  1766.                         
  1767.                         if (file->Exists())
  1768.                         {
  1769.                             FSSpec targetFSSpec = file->GetFileSpec();
  1770.                             RespecifyToTempFolder(file);
  1771.                             FSSpec tmpFileFSSpec = file->GetFileSpec();
  1772.                             CloneIntoFile(ev, theDragItem, tmpFileFSSpec);
  1773.                             // Not notifying the target through SetDragItemData on purpose becuase we are going all the work.
  1774.                             
  1775.                             gTargetFSSpec = targetFSSpec;
  1776.                             gTmpFileFSSpec = tmpFileFSSpec;
  1777.                             self->SetShouldSendReplaceFileEvent(ev, kODTrue);
  1778.                         }
  1779.                         else
  1780.                         {
  1781.                             CloneIntoFlavor(ev, self, theDragItem,
  1782.                                         theDrag, theItem, theType,
  1783.                                         dropFSSpec);
  1784.                         }                
  1785.                     }
  1786.                 }
  1787.                 // If we are not dragging to a file, create a Drag item for the Bento Container.
  1788.                 // This allows other applications to support OpenDoc Bento types (like the Scrapbook, 
  1789.                 // or Container apps).
  1790.                 else if ( result == fnfErr )
  1791.                 {
  1792.                     ODULong dropResult;
  1793.  
  1794.                     // At this point, Doug says only a memory container is being
  1795.                     // modified in any way, so we can suppress fatal errors:
  1796.                     TempSuppressFatalBentoError tempSuppress;
  1797.                     
  1798.                     ODSShort    mouseDownModifiers;
  1799.                     ODSShort    mouseUpModifiers;
  1800.                             
  1801.                     GetDragModifiers(self->GetDragReference(ev), 0L, &mouseDownModifiers, &mouseUpModifiers);
  1802.  
  1803.                     // Check the mandatory modifier keys first. We want to allow moving to a non-OpenDoc process,
  1804.                     // instead of just copies.
  1805.                     
  1806.                     if (mouseUpModifiers & controlKey) 
  1807.                         dropResult = kODDropMove;
  1808.                     else
  1809.                         dropResult = kODDropCopy;
  1810.                     
  1811.                     OSErr e = 
  1812.                     CopyMemContainerToDragItemInChunks( ev, self->GetSession(ev), theType, theItem, theDrag, theDragItem );
  1813.  
  1814.                     dropResult = kODDropFail;        // Dragged to non OpenDoc process, so return fail so part will
  1815.                                                     // post undo action.    
  1816.                     self->SetDropResult(ev, dropResult);
  1817.                     return e;
  1818.                 }
  1819.             }
  1820.             break;
  1821.             default:
  1822. #ifdef ODDebug_DragAndDrop
  1823.     somPrintf("MySendDataProc: Default\n");
  1824. #endif
  1825.                 self->SetDropResult(ev, kODDropFail);
  1826.                 translate = self->GetSession(ev)->GetTranslation(ev);
  1827.                 theISOType = translate->GetISOTypeFromPlatformType(ev, theType, kODPlatformDataType);
  1828.                 if (ODSUExistsThenFocus(ev, theDragItem->GetStorageUnit(ev),kODPropContents, theISOType))
  1829.                 {
  1830.                     result = CopyToDragItemInChunks(ev, theType, theItem, theDrag, theDragItem);
  1831.                     if (result == noErr)
  1832.                         self->SetDropResult(ev, kODDropCopy);
  1833.                 }
  1834.                 else if ( (theType == kODScrapTypestyl) && StorageUnitGetStylFromStyledText(theDragItem->GetStorageUnit(ev), ev, &stylSize, &stylPtr) )
  1835.                 {
  1836.                     result = SetDragItemFlavorData(theDrag, theItem, theType, stylPtr, stylSize, 0L);
  1837.                     WASSERTM(result == noErr, "Error from SetDragItemFlavorData in send procedure");        
  1838.                     if (result == noErr)
  1839.                         self->SetDropResult(ev, kODDropCopy);
  1840.                     ODDisposePtr(stylPtr);
  1841.                     stylPtr = kODNULL;
  1842.                 }
  1843.                 else
  1844.                 {
  1845.                     WARN("Send procedure can not supply this type");        
  1846.                     result = badDragFlavorErr;
  1847.                 }
  1848.                 ODDisposePtr(theISOType);
  1849.             }
  1850.         }
  1851.  
  1852.     CATCH_ALL
  1853.     
  1854.     self->SetShouldSendReplaceFileEvent(ev, kODFalse);
  1855.     result = ErrorCode();
  1856.     WARN("MySendDataProc: %d", result); 
  1857.     
  1858.     ENDTRY
  1859.     
  1860.     return result;
  1861. }
  1862.  
  1863. static OSErr CopyMemContainerToDragItemInChunks(Environment* ev,
  1864.                                 ODSession* theSession,
  1865.                                 FlavorType theType,
  1866.                                 ItemReference theItem,
  1867.                                 ODPlatformDragReference theDrag,
  1868.                                 ODDragItem* theDragItem) 
  1869. {
  1870.     const ODULong kCopyBlockSize = 512;
  1871.     OSErr    result = noErr;
  1872.     ODPtr     dataPtr;
  1873.     ODULong dataSize;
  1874.     
  1875.     TRY
  1876.         // Now write out the entire Container for the Memory Drag item.
  1877.         ODMemDragItem* tempDItem = (ODMemDragItem*)theDragItem;
  1878.  
  1879.         // Clone the D&D container to a temp draft, then return the data handle from the temp container.
  1880.         // We cannot directly get the data handle from the D&D container, because the full data isn't written
  1881.         // until we close the container, but we can't do that yet because there could be further promises
  1882.         // pending against it.
  1883.         TempODHandle theMemDragItemContainerData = CloneToTempMemContainer( ev,  tempDItem, theSession );        
  1884.  
  1885.         ODLockHandle( theMemDragItemContainerData );
  1886.     
  1887.         dataPtr = *theMemDragItemContainerData;
  1888.         dataSize = ODGetHandleSize( theMemDragItemContainerData );
  1889.         WASSERTM( dataSize != 0, "Zero size memory container handle.");        
  1890.  
  1891.         ODULong currentByte = 0;
  1892.         while ((currentByte < dataSize) && (result == noErr)) {
  1893.             ODULong bytesRead;
  1894.             if( ( dataSize - currentByte )  >= kCopyBlockSize )
  1895.                 bytesRead = kCopyBlockSize;
  1896.             else
  1897.                 bytesRead = dataSize - currentByte;
  1898.                 
  1899.             result = SetDragItemFlavorData(theDrag, theItem, theType, ODPtr((ODULong)dataPtr + currentByte), bytesRead, currentByte);
  1900.             WASSERTM(result == noErr, "Error from SetDragItemFlavorData in CopyToDragItemInChunks.");        
  1901.             currentByte += bytesRead;
  1902.         }
  1903.         WASSERTM(currentByte == dataSize, "Bytes written is NOT equal to dataSize.");        
  1904.     CATCH_ALL
  1905.         result = dragNotAcceptedErr;
  1906.     ENDTRY
  1907.     return result;
  1908. }
  1909.  
  1910. static ODHandle CloneToTempMemContainer( Environment* ev, ODMemDragItem* tempDItem, ODSession* theSession )
  1911. {
  1912.     ODStorageUnit* contentSU = tempDItem->GetStorageUnit(ev);
  1913.     ODID targetContentFrameID = kODNULLID;
  1914.     ODHandle containerHandle =    ODNewHandle(0);
  1915.     ODStorageUnitID suID;
  1916.     TRY
  1917.         TempODContainer        tempContainer = CreateMemoryContainer(ev, theSession, containerHandle, kODBentoMemoryContainer);        
  1918.         TempODDocument         tempDocument = tempContainer->AcquireDocument(ev, kODDefaultDocument);
  1919.         TempODDraft         targetDraft = tempDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  1920.         TempODStorageUnit    targetSU    = targetDraft->CreateStorageUnit(ev);
  1921.  
  1922.         { TempODStorageUnit draftProperties = targetDraft->AcquireDraftProperties(ev);
  1923.           ODSetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef,targetSU->GetID(ev));
  1924.           suID = ODGetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef);
  1925.         }
  1926.         
  1927.         ODDraft* sourceDraft = contentSU->GetDraft(ev);                
  1928.         ODDraftKey cloneKey = 0;
  1929.         TRY
  1930.             cloneKey = sourceDraft->BeginClone(ev, targetDraft, kODNULL, kODCloneToFile);
  1931.             sourceDraft->Clone(ev, cloneKey, contentSU->GetID(ev), targetSU->GetID(ev), 0);                
  1932.             ODID contentFrameID = ODGetWeakSURefProp(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef);
  1933.             if (contentFrameID != kODNULLID) 
  1934.             {
  1935.                 targetContentFrameID = sourceDraft->Clone(ev, cloneKey, contentFrameID, kODNULLID, 0);                
  1936.             }        
  1937.             sourceDraft->EndClone(ev, cloneKey);
  1938.         CATCH_ALL
  1939.             sourceDraft->AbortClone(ev, cloneKey);
  1940.             
  1941.         ENDTRY
  1942.         
  1943.         ODSURemoveProperty(ev, targetSU, kODPropMouseDownOffset);    
  1944.  
  1945.         // first externalize the container 
  1946.         // Externalize may fail with an iterator-out-of-sync error because 
  1947.         // resolving promises may add storage units to the draft's collection
  1948.         // during iteration.  In theory, the only promises should be in the
  1949.         // root storage unit, so explicitly externalize it first to resolve
  1950.         // promises before interating over all storage units.
  1951.         if( targetSU )
  1952.             targetSU->Externalize(ev);
  1953.         targetDraft->Externalize(ev);
  1954.         
  1955.     CATCH_ALL
  1956.         ODDisposeHandle( containerHandle );
  1957.         RERAISE;
  1958.     ENDTRY
  1959.     
  1960.     return containerHandle; 
  1961. }
  1962.  
  1963. static void CloneIntoFlavor(Environment* ev, ODDragAndDrop* dad, ODDragItem* theDragItem, 
  1964.                                 ODPlatformDragReference theDrag, ItemReference theItem, FlavorType theType,
  1965.                                 FSSpec dropFSSpec)
  1966. {
  1967.     OSErr result;
  1968.     
  1969.     if ((result = CloneIntoFile(ev, theDragItem, dropFSSpec)) == noErr)
  1970.     {
  1971.         result = SetDragItemFlavorData(theDrag, theItem, theType, &dropFSSpec, sizeof(FSSpec), 0L);
  1972.     }
  1973.     else
  1974.     {
  1975.         dad->SetDropResult(ev, kODDropFail);                
  1976.     }                
  1977. }
  1978.  
  1979. static OSErr CloneIntoFile(Environment* ev, ODDragItem* theDragItem, FSSpec dropFSSpec) 
  1980. {
  1981.     OSErr            err = noErr;
  1982.     PlatformFile    file;
  1983.     file.Specify(&dropFSSpec);
  1984.     
  1985.     TRY
  1986.         ODStorageUnit* contentSU = theDragItem->GetStorageUnit(ev);
  1987.         ODID targetContentFrameID = kODNULLID;
  1988.         OSType    fileType = GetStorageUnitOSType(ev,contentSU);
  1989.         OSType    fileCreator=ODGetIconFilePlatformCreatorFromPartSU(ev,contentSU);
  1990.  
  1991.         file.Create(fileCreator, fileType, smSystemScript);
  1992.         SetFinderInfo(ev, contentSU, &file);
  1993.         SetIconFamily(ev, contentSU, &file);
  1994.         TempODContainer targetContainer    = CreateFileContainer(ev, contentSU->GetSession(ev), &file.GetFileSpec());
  1995.         TempODDocument    targetDocument    = targetContainer->AcquireDocument(ev, kODDefaultDocument);
  1996.         TempODDraft        targetDraft     = targetDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  1997.         TempODStorageUnit     targetDraftProperties = targetDraft->AcquireDraftProperties(ev);
  1998.         TempODStorageUnit    targetSU    = targetDraft->CreateStorageUnit(ev);
  1999.         ODSetStrongSURefProp(ev, targetDraftProperties, kODPropRootPartSU,kODStrongStorageUnitRef, targetSU->GetID(ev));
  2000.         ODDraft* sourceDraft = contentSU->GetDraft(ev);                
  2001.         ODDraftKey cloneKey = 0;
  2002.         TRY
  2003.             cloneKey = sourceDraft->BeginClone(ev, targetDraft, kODNULL, kODCloneToFile);
  2004.             sourceDraft->Clone(ev, cloneKey, contentSU->GetID(ev), targetSU->GetID(ev), 0);                
  2005.             ODID contentFrameID = ODGetWeakSURefProp(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef);
  2006.             if (contentFrameID != kODNULLID) 
  2007.             {
  2008.                 targetContentFrameID = sourceDraft->Clone(ev, cloneKey, contentFrameID, kODNULLID, 0);                
  2009.             }        
  2010.             sourceDraft->EndClone(ev, cloneKey);
  2011.         CATCH_ALL
  2012.             sourceDraft->AbortClone(ev, cloneKey);
  2013.         ENDTRY
  2014.         
  2015.         if (targetContentFrameID != kODNULLID)
  2016.             ODSetStrongSURefProp(ev, targetDraftProperties, kODPropRootFrameList, kODStrongStorageUnitRefs, targetContentFrameID);
  2017.  
  2018.         ODSURemoveProperty(ev, targetSU, kODPropMouseDownOffset);
  2019.  
  2020.         targetDraft->Externalize(ev);        
  2021.     CATCH_ALL
  2022.     
  2023.         file.Delete();        
  2024.         err = dragNotAcceptedErr;
  2025.         WARN("Error caught in CloneIntoFile.");
  2026.     ENDTRY
  2027.     
  2028.     return err;
  2029. }
  2030.  
  2031. static boolean MakeUniqueFilename( Environment *ev, ODSession* session, ODStorageUnit *su, FSSpec* spec )
  2032. {
  2033.     const ODULong kODMaxFileNameSize = 63;
  2034.     
  2035.     Str255 prefix;
  2036.     prefix[0] = 0;
  2037.     boolean nameFromPart = false;
  2038.     TempPlatformFile file = new PlatformFile;
  2039.     file->Specify(spec);
  2040.     
  2041.     TRY
  2042.         // Get the name of the part
  2043.         if (su->Exists(ev, kODPropName, kODMacIText, 0))
  2044.         {
  2045.             ODIText* rootPartName = ODGetITextProp(ev, su, kODPropName, kODMacIText, kODNULL);
  2046.             if (rootPartName)
  2047.             {
  2048.                 GetITextPString(rootPartName, prefix);
  2049.                 DisposeIText(rootPartName);
  2050.                 p2cstr(prefix);
  2051.                 file->SetAsciiName((char*) prefix);    
  2052.                 nameFromPart = true;
  2053.             }
  2054.         }
  2055.     
  2056.         if (!prefix[0])
  2057.         {        
  2058.             // Get the category of the part if a name cannot be found.
  2059.             ODName* categoryName = kODNULL;
  2060.             TRY
  2061.                 categoryName = ODGetCatFromPartSU(ev, su, session->GetNameSpaceManager(ev));
  2062.             CATCH_ALL
  2063.             ENDTRY
  2064.             // If the above call throws, then most likely we were trying to get the category for NoPart.
  2065.             // So, set the category name for NoPart appropriately.
  2066.             if( !categoryName)
  2067.             {
  2068.                 ODGetString( prefix, kODUnknownCategoryStr );
  2069.                 p2cstr(prefix);
  2070.             }
  2071.             if (categoryName)
  2072.             {
  2073.                 GetITextPString(categoryName, prefix);
  2074.                 p2cstr(prefix);
  2075.             }
  2076.             file->SetAsciiName((char*) prefix);    
  2077.             file->UniquifyName(kODNoResourceID,
  2078.                                 kODNULL,
  2079.                                 kODCategoryNumberSuffix,
  2080.                                 kODNULL,
  2081.                                 1,
  2082.                                 kSpecifyNewNameOnly,
  2083.                                 kODForceNewName);
  2084.             ODDisposePtr(categoryName);
  2085.             nameFromPart = false;
  2086.         }
  2087.     CATCH_ALL
  2088.     ENDTRY
  2089.         
  2090.     *spec = file->GetFileSpec();
  2091.     return nameFromPart;
  2092. }
  2093.  
  2094. static OSType GetStorageUnitOSType( Environment *ev, ODStorageUnit *su )
  2095. {
  2096.     OSType    returnType = kODShellSignature;
  2097.  
  2098. #if ODDebug_DragAndDrop
  2099.     ODULong    numProperties = su->CountProperties(ev);
  2100.     su->Focus(ev, kODNULL, kODPosAll, kODNULL, 0, kODPosAll);
  2101.     for (ODULong i = 1; i <= numProperties; i++) {
  2102.         su->Focus(ev, kODNULL, kODPosNextSib,kODNULL,0,kODPosAll);
  2103.         ODPropertyName name = su->GetProperty(ev);
  2104.         ODDisposePtr(name);
  2105.     }
  2106. #endif
  2107.     
  2108.     returnType = ODGetIconFilePlatformTypeFromPartSU(ev, su);
  2109.     
  2110.     return returnType;
  2111. }
  2112.  
  2113.  
  2114. static OSErr CopyToDragItemInChunks(Environment* ev,
  2115.                                 FlavorType theType,
  2116.                                 ItemReference theItem,
  2117.                                 ODPlatformDragReference theDrag,
  2118.                                 ODDragItem* theDragItem) 
  2119. {
  2120.     const ODULong kCopyBlockSize = 512;
  2121.     OSErr    result = noErr;
  2122.     ODPtr     dataPtr = ODNewPtr(kCopyBlockSize);
  2123.     ODULong dataSize = theDragItem->GetStorageUnit(ev)->GetSize(ev);
  2124.     
  2125.     ODULong currentByte = 0;
  2126.     while ((currentByte < dataSize) && (result == noErr)) {
  2127.         ODULong bytesRead = StorageUnitGetValue(theDragItem->GetStorageUnit(ev), ev, kCopyBlockSize, dataPtr);
  2128.         result = SetDragItemFlavorData(theDrag, theItem, theType, dataPtr, bytesRead, currentByte);
  2129.         WASSERTM(result == noErr, "Error from SetDragItemFlavorData in CopyToDragItemInChunks.");        
  2130.         currentByte += bytesRead;
  2131.     }
  2132.     ODDisposePtr(dataPtr);
  2133.     WASSERTM(currentByte == dataSize, "Bytes written is NOT equal to dataSize.");        
  2134.     
  2135.     return result;
  2136. }
  2137.  
  2138. static OSErr CopyFromDragItemInChunks(Environment* ev,
  2139.                                 FlavorType theType,
  2140.                                 ItemReference theItem,
  2141.                                 ODPlatformDragReference theDrag,
  2142.                                 ODStorageUnitView* destSUView) 
  2143. {
  2144.     const ODULong kCopyBlockSize = 512;
  2145.     OSErr    result = noErr;
  2146.     ODPtr     dataPtr = ODNewPtr(kCopyBlockSize);
  2147.     long    dataSize = 0;
  2148.     ODULong    totalRead = 0;
  2149.     ODULong    oldValueSize = destSUView->GetSize(ev);
  2150.     
  2151.     result = GetFlavorDataSize(theDrag, theItem, theType, &dataSize);
  2152.     while ((totalRead < dataSize) && (result == noErr)) {
  2153.         Size bytesRead = dataSize - totalRead;
  2154.         if (bytesRead > kCopyBlockSize)
  2155.             bytesRead = kCopyBlockSize;
  2156.         result = GetFlavorData(theDrag, theItem, theType, dataPtr, &bytesRead, totalRead);
  2157.         WASSERTM(result == noErr, "Error from GetFlavorData in CopyFromDragItemInChunks.");        
  2158.         StorageUnitViewSetValue(destSUView, ev, bytesRead, dataPtr);
  2159.         totalRead += bytesRead;
  2160.     }
  2161.     ODDisposePtr(dataPtr);
  2162.  
  2163.     ODULong newValueSize = destSUView->GetOffset(ev);
  2164.     if (oldValueSize > newValueSize)
  2165.         destSUView->DeleteValue(ev, oldValueSize - newValueSize);
  2166.  
  2167.     return result;
  2168. }
  2169.  
  2170.  
  2171. #ifdef ODDebug_DragAndDrop
  2172. void PrintDragReference(ODPlatformDragReference dragRef, char* header)
  2173. {
  2174.     unsigned short    items = 0;
  2175.     CountDragItems(dragRef, &items);
  2176.     somPrintf("%s: fDragReference %x numItems %d\n", header, dragRef, items);
  2177.     for (unsigned short i = 1; i <= items; i++) {
  2178.         ItemReference    itemRef;
  2179.         GetDragItemReferenceNumber(dragRef, i, &itemRef);
  2180.         unsigned short numFlavors = 0;
  2181.         CountDragItemFlavors(dragRef, itemRef, &numFlavors);
  2182.         FlavorType theType;
  2183.         Size    dataSize = 0;
  2184.         for (unsigned short j = 1; j <= numFlavors; j++) {
  2185.             GetFlavorType (dragRef, itemRef, j, &theType);
  2186.             GetFlavorDataSize(dragRef, itemRef, theType, &dataSize);
  2187.             somPrintf("%s: itemRef %x item %d flavor %d size %d type ", header, itemRef, i, j, dataSize);
  2188.             for (short k = 0; k <= 3; k++) {
  2189.                 somPrintf("%c", ((char*) &theType)[k]);
  2190.             }
  2191.             somPrintf("\n");
  2192.             if ((theType == 'hfs ') && (dataSize > 0)) {
  2193.                 HFSFlavor hfsFlavor;
  2194.                 GetFlavorData(dragRef,itemRef,theType,&hfsFlavor,&dataSize,0);
  2195.                 somPrintf("type %x creator %x name %s\n", hfsFlavor.fileType, hfsFlavor.fileCreator, p2cstr(hfsFlavor.fileSpec.name));
  2196.             }
  2197.         }
  2198.     }
  2199. }
  2200.  
  2201. void PrintStorageUnit(Environment* ev, ODStorageUnit* su, char* header)
  2202. {
  2203.     ODStorageUnitCursor* cursor = su->CreateCursorWithFocus(ev);
  2204.     
  2205.     ODULong numProperties = su->CountProperties(ev);
  2206.     su->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosUndefined);
  2207.     ODULong numValues = su->CountValues(ev);
  2208.     somPrintf("%s: su %x numProperties %d numContentValues %d\n", header, su, numProperties, numValues);
  2209.     for (short i = 1; i <= numValues; i++) {
  2210.         su->Focus(ev, kODNULL, kODPosSame, kODNULL, i, kODPosUndefined);
  2211.         ODValueType type = su->GetType(ev);
  2212.         somPrintf("%s: Type %d %s\n", header, i, type);
  2213.         ODDisposePtr(type);
  2214.     }
  2215.     
  2216.     su->FocusWithCursor(ev, cursor);
  2217.     delete cursor;
  2218. }
  2219.  
  2220. #endif
  2221.  
  2222. SOM_Scope OSErr  SOMLINK ODDragAndDropEnterHandler(ODDragAndDrop *somSelf, Environment *ev,
  2223.         ODPlatformDragReference theDrag)
  2224. {
  2225.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2226.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropEnterHandler");
  2227.  
  2228. #if ODDebug_DragAndDrop
  2229.     somPrintf("In EnterHandler.\n");
  2230. #endif        
  2231.  
  2232.     OSErr            returnCode = noErr;
  2233.  
  2234.     ODVolatile(returnCode);
  2235.     SOM_TRY
  2236.         OSErr            result = noErr;
  2237.         ODDragLink*        newLink = kODNULL;
  2238.         ODUShort        items = 0;
  2239.         
  2240.         CountDragItems(theDrag, &items);
  2241.         for (ODUShort i = 1; i <= items; ++i)
  2242.         {    
  2243.             ItemReference    itemID;
  2244.             FlavorFlags        theFlags;
  2245.             result = GetDragItemReferenceNumber(theDrag, i, &itemID);
  2246.             result = GetFlavorFlags(theDrag, itemID, kODPromiseFlavor, &theFlags);
  2247.             if (result == noErr)
  2248.             {
  2249.                 if (_fDragReference != theDrag)
  2250.                 {    
  2251.                     _fListFromHandler = kODTrue;
  2252.                     newLink = new ODDragLink((ODDragItem*)itemID, kODFalse);
  2253.                     _fDragItemList->AddLast((Link*)newLink);
  2254.                 }
  2255.             }
  2256.             else if (result == badDragFlavorErr)
  2257.             {    ODStorageSystem*    storage = _fStorageSystem;
  2258.                 ODTranslation*        translate = _fSession->GetTranslation(ev);
  2259.                 ODDragItem*            newItem = kODNULL;        ODVolatile(newItem);
  2260.                 
  2261.                 ODUShort    count;            
  2262.                 ODUShort    j = 1;
  2263.                 HFSFlavor*    hfsFlavor = (HFSFlavor*)ODNewPtr( sizeof(HFSFlavor) );
  2264.                 CountDragItemFlavors(theDrag, itemID, &count);
  2265.     
  2266.                 // Do something special for: Bento files, Finder files, and data
  2267.                 // interchange container types.
  2268.                 for (j = 1; (j <= count) && (newItem == kODNULL); j++)
  2269.                 {   OSType    theType;
  2270.                     OSErr    err         = GetFlavorType(theDrag, itemID, j, &theType);
  2271.                     if ((err == noErr) && (theType == flavorTypeHFS))
  2272.                     {  
  2273.                          Size  dataSize = sizeof(HFSFlavor);
  2274.                         OSErr err = GetFlavorData(theDrag, itemID, theType, hfsFlavor,
  2275.                                                   (Size*) &dataSize, 0);
  2276.                         if (err == noErr)
  2277.                         {    
  2278.                             FSSpec* targetFileSpec = &(hfsFlavor->fileSpec);
  2279.                             if (IsOpenDocDocument(hfsFlavor))
  2280.                             {    
  2281.                             // The item is a Bento file container; create the update container for it.
  2282.                                 // Later we will put the HFS info in it, even if it is a read-only file.
  2283.                                 ODBoolean wasAliased;
  2284.                                 ODBoolean targetIsFolder;
  2285.                                 OSErr err = ResolveAliasFile(targetFileSpec, TRUE, &targetIsFolder, &wasAliased);
  2286.                                 if ((err == noErr)  && (!targetIsFolder)) {
  2287.                                     FInfo    finderInfo;
  2288.                                     err = FSpGetFInfo(targetFileSpec, &finderInfo);
  2289.                                     if ((err == noErr) && IsOpenDocDocument(hfsFlavor /*finderInfo.fdType*/)) {
  2290.                                         ODByteArray*    ba = CreateByteArray(targetFileSpec, sizeof(FSSpec));
  2291.                                         TRY
  2292.                                             newItem = new(ODGetDefaultHeap()) ODFileDragItem(storage, kODTrue,
  2293.                                                                                 theDrag, itemID, hfsFlavor);
  2294.                                             ((ODFileDragItem*) newItem)->Initialize(ev, ba);
  2295.                                         CATCH_ALL
  2296.                                             delete newItem;
  2297.                                             newItem = kODNULL;
  2298.                                         ENDTRY
  2299.                                         DisposeByteArray(ba);
  2300.                                     }
  2301.                                 }
  2302.                             }
  2303.                             else if( IsOpenDocClipping( hfsFlavor ) )
  2304.                             {
  2305.                                 // The user has dragged in a clipping that has Bento container data.
  2306.                                 // While we will get a drag flavor of type kODBentoFlavor that we could have
  2307.                                 // loaded in a later section just like the data had come from the Scrapbook,
  2308.                                 // the Finder won't resolve its promise for that data to the Drag Manager,
  2309.                                 // so we can't use the Drag Manager API to load the data.
  2310.                                 // Instead, we need to load the data directly from the clipping's resource fork.
  2311.  
  2312.                                 ODHandle tempHandle = kODNULL; ODVolatile( tempHandle );                                
  2313.  
  2314.                                 TRY
  2315.                                     tempHandle = ReadClippingFileOpenDocData( hfsFlavor );
  2316.                                     if( tempHandle == kODNULL )
  2317.                                         THROW( kODErrDragTrackingException );
  2318.                                     ODLockHandle( tempHandle );
  2319.                                     newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, tempHandle,
  2320.                                                                                     kODTrue,theDrag, itemID, kODNULL);
  2321.                                     ODUnlockHandle(tempHandle);
  2322.                                 CATCH_ALL
  2323.                                     if( newItem )
  2324.                                         { ODDeleteObject( newItem ); }
  2325.                                     else
  2326.                                     { 
  2327.                                         if( tempHandle != kODNULL )
  2328.                                             ODDisposeHandle( tempHandle ); 
  2329.                                     }
  2330.                                     RERAISE;
  2331.                                 ENDTRY
  2332.  
  2333.                             }
  2334.                             else
  2335.                             {    if( _fMemItemContainer == kODNULL)
  2336.                                 {
  2337.                                     ODHandle memContainerHandle = ODNewHandle(0);
  2338.                                     _fMemItemContainer = CreateMemoryContainer(ev, _fSession,
  2339.                                                 memContainerHandle, kODBentoMemoryContainer);
  2340.                                     // _fMemItemContainer->Acquire(ev);    
  2341.                                     ODDocument* theDocument = _fMemItemContainer->AcquireDocument( ev, kODDefaultDocument );
  2342.                                     _fCachedMemContainerDraft = theDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  2343.                                     // Refs to container/doc/draft will be released in Clear method.
  2344.                                 }
  2345.                                 newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, _fCachedMemContainerDraft,
  2346.                                                                         kODTrue, theDrag, itemID, hfsFlavor);
  2347.                                 ((ODMemDragItem*) newItem)->Initialize(ev);
  2348.                             }
  2349.                         }
  2350.                     }
  2351.                     if( theType == kODBentoFlavor )
  2352.                     {
  2353.                         // The item is a memory container handle that had been either:
  2354.                         // a) Dragged to a non-OpenDoc process (like the Scrapbook) then dragged back.
  2355.                         // b) Put on the Clipboard, pasted into non-OpenDoc process, then dragged back.
  2356.                         // So, recreate the memory container.
  2357.                         ODHandle tempHandle = kODNULL;
  2358.                         ODVolatile( tempHandle );
  2359.                         TRY
  2360.                              Size flavorSize = 0;
  2361.  
  2362.                             OSErr DragSizeErr = GetFlavorDataSize( theDrag, itemID, theType, &flavorSize );
  2363.                             if( DragSizeErr != noErr )
  2364.                                 THROW( DragSizeErr );
  2365.                             tempHandle = ODNewHandle( flavorSize );
  2366.                             ODLockHandle( tempHandle );
  2367.                             OSErr DragDataErr = GetFlavorData(theDrag, itemID, theType, *tempHandle, (Size*) &flavorSize, 0);
  2368.                             if( DragDataErr != noErr )
  2369.                                 THROW( DragDataErr );
  2370.                             ODUnlockHandle(tempHandle);
  2371.                             newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, tempHandle,
  2372.                                                                             kODTrue,theDrag, itemID, kODNULL);
  2373.                         CATCH_ALL
  2374.                             if( newItem )
  2375.                                 { ODDeleteObject( newItem ); }
  2376.                             else
  2377.                                 { ODDisposeHandle( tempHandle ); }
  2378.                             if( MemError() != noErr || ErrorCode() != -1854 )    // -1854 = cantGetFlavorErr
  2379.                             {
  2380.                                 RERAISE;                
  2381.                                 // We could get error -1854 because we are trying to load data from a
  2382.                                 // clipping, and the Finder will not resolve drag promises at DragTrack time.
  2383.                                 // Therefor, we will load OpenDoc data from clippings in the routine
  2384.                                 // above in the hfs secion, and do not need to Reraise this error.
  2385.                                 // But, we do want to reraise it when we get it because we are out of memory,
  2386.                                 // which means that there really was an error loading the flavor data or
  2387.                                 // getting its size.
  2388.                             }
  2389.                         ENDTRY
  2390.                     }
  2391.                 }
  2392.                 if (newItem == kODNULL)
  2393.                 {    // Otherwise, the item was neither a memory or file container.
  2394.                     // Just make a new drag item for it. We will use one container to
  2395.                     // hold all non-container data, and just create new storage units for
  2396.                     // each new item.
  2397.                     if( _fMemItemContainer == kODNULL ) {
  2398.                         ODHandle memContainerHandle = ODNewHandle(0);
  2399.                         _fMemItemContainer = CreateMemoryContainer(ev, _fSession,
  2400.                                                 memContainerHandle, kODBentoMemoryContainer);
  2401.                         // _fMemItemContainer->Acquire(ev);            
  2402.                         ODDocument* theDocument = _fMemItemContainer->AcquireDocument( ev, kODDefaultDocument );
  2403.                         _fCachedMemContainerDraft = theDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  2404.                         // Refs to container/doc/draft will be released in Clear method.
  2405.                     }
  2406.                     newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, _fCachedMemContainerDraft, kODTrue, theDrag,
  2407.                                                                                 itemID, hfsFlavor);
  2408.                     ((ODMemDragItem*) newItem)->Initialize(ev);
  2409.                 }
  2410.                 _fListFromHandler = kODTrue;
  2411.                 newLink = new ODDragLink(newItem, kODTrue);
  2412.                 _fDragItemList->AddLast((Link*)newLink);
  2413.             }
  2414.             else
  2415.             {    WASSERTM(result == noErr, "Error from GetFlavorFlags in tracking handler");
  2416.                 returnCode = result;
  2417.                 break;
  2418.             }
  2419.         }
  2420.         _fDragReference = theDrag;
  2421.         _fAttributes = 0;
  2422.         if (_fListFromHandler)
  2423.         {    LinkedListIterator*    newIter = new LinkedListIterator(_fDragItemList);
  2424.             ODDragItemIterator* tmpIter = new ODDragItemIterator();
  2425.             THROW_IF_NULL(tmpIter, kODErrOutOfMemory);
  2426.             tmpIter->InitDragItemIterator(ev, newIter);
  2427.             _fDragItemIterator = tmpIter;
  2428.         }
  2429.     
  2430.         ODDeleteObject(_fFacetsRejected);
  2431.         
  2432.     SOM_CATCH_ALL    
  2433.     
  2434.         returnCode = ErrorCode();
  2435.         ODDeleteObject(_fFacetsRejected);
  2436.         if (_fDragItemList)
  2437.             _fDragItemList->DeleteAllLinks();
  2438.         
  2439.     SOM_ENDTRY
  2440.     
  2441.     _fFacetsRejected = new OpenHashTable(OpenHashTable::StdEqual, OpenHashTable::StdHash, kODNULL);
  2442.     _fFacetsRejected->Initialize(kODInitialNumEntries,
  2443.                                     sizeof(ODFacet*),
  2444.                                     sizeof(ODFacet*));
  2445.     
  2446.     return returnCode;
  2447. }
  2448.  
  2449. SOM_Scope OSErr  SOMLINK ODDragAndDropEnterWindow(ODDragAndDrop *somSelf, Environment *ev,
  2450.         ODPlatformDragReference theDrag,
  2451.         ODPlatformWindow theWindow)
  2452. {
  2453.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2454.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropEnterWindow");
  2455.     
  2456.     // This is a private method called only from MyDragTrackingHandler.
  2457.     // It can do without its own SOM_TRY.
  2458.  
  2459. #if ODDebug_DragAndDrop
  2460.     somPrintf("Enter EnterWindow.\n");
  2461. #endif
  2462.  
  2463.     ODPoint            mouse, localMouse;
  2464.     Point            qdMouse;
  2465.     ODFacet*        targetFacet = kODNULL;
  2466.     ODBoolean        handled = kODFalse;
  2467.     
  2468.     GetDragMouse(theDrag, &qdMouse, 0L);
  2469.     mouse = qdMouse;
  2470.     targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2471.     
  2472.     if (!targetFacet)
  2473.         _fAttributes &= kODDragHasLeftSourcePartMask;
  2474.     else
  2475.     {
  2476.         while (targetFacet && !handled)
  2477.         {
  2478.             if ((targetFacet->GetFrame(ev) == _fSourceFrame) && (_fHasLeftSourceFrame == kODFalse)) {
  2479.                 _fAttributes |= kODDragIsInSourcePart;
  2480.                 _fAttributes |= kODDragIsInSourceFrame;
  2481.             }
  2482.             else
  2483.             {
  2484.                 _fHasLeftSourceFrame = kODTrue;
  2485.                 ODPart* targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2486.                 if (targetPart == _fSourcePart)
  2487.                     _fAttributes = kODDragIsInSourcePart;
  2488.                 else {
  2489.                     _fHasLeftSourcePart = kODTrue;
  2490.                     _fAttributes = 0;
  2491.                 }
  2492.                 ODReleaseObject(ev, targetPart);
  2493.             }
  2494.             handled = targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2495.             if (!handled)
  2496.             {
  2497.                 _fFacetsRejected->ReplaceEntry(&targetFacet, &targetFacet);
  2498.                 targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2499.             }
  2500.         }
  2501.     }
  2502.     _fPrevFacet = targetFacet;
  2503.     
  2504.     return noErr;
  2505. }
  2506.  
  2507. SOM_Scope OSErr  SOMLINK ODDragAndDropInWindow(ODDragAndDrop *somSelf, Environment *ev,
  2508.         ODPlatformDragReference theDrag,
  2509.         ODPlatformWindow theWindow)
  2510. {
  2511.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2512.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropInWindow");
  2513.  
  2514.     ODPoint            mouse, localMouse;
  2515.     Point            qdMouse;
  2516.     ODFacet*        targetFacet = kODNULL;
  2517.     ODBoolean        handled = kODFalse;
  2518.     
  2519.     SOM_TRY
  2520.     
  2521.         GetDragMouse(theDrag, &qdMouse, 0L);
  2522.         mouse = qdMouse;
  2523.         // Get the facet under the current mouse location.
  2524.         targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2525.         
  2526.         // We are leaving the window, call DragLeave on the last facet and return
  2527.         if (!targetFacet) {
  2528.             _fAttributes &= kODDragHasLeftSourcePartMask;
  2529.             if (_fPrevFacet) {
  2530.                 _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2531.             }
  2532.         }
  2533.         // Otherwise, the mouse is still in the OpenDoc window.
  2534.         else
  2535.         {    
  2536.             // Since the mouse is still in the OpenDoc window, we want to implement the following protocal for
  2537.             // having different facets draw drag highlighting. Everytime the mouse moves and is still in the window:
  2538.             // A. If the mouse enters a new facet, call DragEnter on the new one.
  2539.             //       1. If the new facet can't accept the drag, call DragEnter on the next containg facet.
  2540.             // B. If the mouse stays within the same facet, call DragWithin on that facet again.
  2541.             // C. If the mouse leaves a facet, call DragLeave on the facet.
  2542.             // We don't want drag-highlighiting to take place on the frame that originates the drag,
  2543.             // unless the mouse leaves the frame, then enters it again. So, we do the following:
  2544.             //    1. Store a refernce to the frame that originated the drag..
  2545.             //      2. Define a boolean that signifies that the mouse has not left the source frame.
  2546.             //      3. While the mouse is still in the source frame, tell the part not to do any drag-hiliting as above.
  2547.             //      4. When the mouse leaves the source frame, set the boolean that signifies we have not left the source
  2548.             //         to false. This tells subsequent parts to do hilighting following the above algorithm.
  2549.  
  2550.             // We basically want to do one of the following in this loop:
  2551.             //    1. Track that the mouse has entered a new facet and call DragEnter on it.
  2552.             //    2. Track that the mouse has left a facet and call DragLeave on it.
  2553.             //    3. Track that the mouse is still in a facet and call DragWithin on it.
  2554.             // Obviously there are special cases to all of the above. See the source comments below for more info.
  2555.             while (targetFacet && !handled)
  2556.             {   
  2557.                 // Check whether we are still in the source frame, and haven't ever left it. If so, no hiliting needed.
  2558.                 if ((targetFacet->GetFrame(ev) == _fSourceFrame) && (_fHasLeftSourceFrame == kODFalse)) {
  2559.                     _fAttributes |= kODDragIsInSourcePart;
  2560.                     _fAttributes |= kODDragIsInSourceFrame;
  2561.                 }
  2562.                 // Otherwise, we are either in a new frame, or we have left and reenter the source frame. 
  2563.                 // Tell the part to start doing hiliting.
  2564.                 else {
  2565.                     _fHasLeftSourceFrame = kODTrue;
  2566.                     ODPart* targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2567.                     if (targetPart == _fSourcePart)
  2568.                         _fAttributes = kODDragIsInSourcePart;
  2569.                     else {
  2570.                         _fHasLeftSourcePart = kODTrue;
  2571.                         _fAttributes = 0;
  2572.                     }
  2573.                     ODReleaseObject(ev, targetPart);
  2574.                 }
  2575.                 if (_fPrevFacet == targetFacet)  {
  2576.                     handled = targetFacet->DragWithin(ev, &localMouse, _fDragItemIterator, kODNULL);
  2577.                 }
  2578.                 else {
  2579.                 // We need to call DragLeave on the previous facet before we call DragEnter on the new one, even
  2580.                 // though the DragEnter can return false. Why not call DragEnter first, decide if it succeeds, then
  2581.                 // call DragLeave? Because of ShowDragHilite and HideDragHilite Drag Manager functions need this
  2582.                 // order or drag hiliting is messed up.
  2583.                     if( _fPrevFacet )
  2584.                         _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2585.                     handled = targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2586.     //                if ( _fPrevFacet && !handled ) {
  2587.     //                    targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2588.     //                }
  2589.                 }
  2590.                 if (!handled)
  2591.                 {
  2592.                 // If any facet rejects a particular drag, then at no time during the current will it ever
  2593.                 // accept it again. A part can only handle certain drag kinds, and that will not change during
  2594.                 // a drag. So, if a drag is rejected, keep a list of facets that have rejected the current
  2595.                 // drag and don't try to do hiliting for them again for this drag.
  2596.                     _fFacetsRejected->ReplaceEntry(&targetFacet, &targetFacet); 
  2597.                     // On of the following happened previous to this statement:
  2598.                     // DragWithin or DragEnter was called on a facet and the part returned false.
  2599.                     // So, give the container a crack at the drag.
  2600.                     targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2601.                     if( targetFacet )
  2602.                         targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2603.                     // else the root rejected the drag and there is no container to take the drag. Will just
  2604.                     // exit this loop.
  2605.                 }
  2606.             }
  2607.         }
  2608.         _fPrevFacet = targetFacet;
  2609.     
  2610.     SOM_CATCH_ALL
  2611.     SOM_ENDTRY
  2612.  
  2613.     return noErr;
  2614. }
  2615.  
  2616. SOM_Scope OSErr  SOMLINK ODDragAndDropLeaveWindow(ODDragAndDrop *somSelf, Environment *ev,
  2617.         ODPlatformDragReference theDrag,
  2618.         ODPlatformWindow theWindow)
  2619. {
  2620.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2621.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropLeaveWindow");
  2622.  
  2623. #if ODDebug_DragAndDrop
  2624.     somPrintf("In LeaveWindow.\n");
  2625. #endif        
  2626.  
  2627.     SOM_TRY
  2628.         ODPoint            mouse, localMouse;
  2629.         Point            qdMouse;
  2630.         
  2631.         GetDragMouse(theDrag, &qdMouse, 0L);
  2632.         mouse = qdMouse;
  2633.         ODFacet* dummyTargetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2634.     
  2635.         _fAttributes = 0;
  2636.         if (_fPrevFacet) {
  2637.             _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2638.             _fPrevFacet = kODNULL;
  2639.         }
  2640.     SOM_CATCH_ALL
  2641.     SOM_ENDTRY
  2642.     
  2643.     _fHasLeftSourceFrame = kODTrue;
  2644.     _fHasLeftSourcePart = kODTrue;
  2645.  
  2646.     return noErr;
  2647. }
  2648.  
  2649. SOM_Scope OSErr  SOMLINK ODDragAndDropLeaveHandler(ODDragAndDrop *somSelf, Environment *ev)
  2650. {
  2651.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2652.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropLeaveHandler");
  2653.  
  2654. #if ODDebug_DragAndDrop
  2655.     somPrintf("In LeaveHandler.\n");
  2656. #endif        
  2657.     
  2658.     // Now undo the damage done in the dragTrackingEnterHandler section.
  2659.     // NOTE: It is OK to blow away the drag items here because at this point
  2660.     // the drop handler will already have processed the drop if any.
  2661.     if (_fListFromHandler)
  2662.     {
  2663.         TRY{
  2664.             somSelf->Clear(ev);
  2665.         }CATCH_ALL{
  2666.             // ignore error
  2667.         }ENDTRY
  2668.         _fListFromHandler = kODFalse;
  2669.         _fDragReference = 0;
  2670.     }
  2671.     _fAttributes = 0;
  2672.     
  2673.     return noErr;
  2674. }
  2675.  
  2676. static void    SetIconFamily(Environment* ev, ODStorageUnit* fromSU, PlatformFile* file)
  2677. {
  2678.     static const ResType            kIconType[6] = {'ICN#','icl4','icl8','ics#','ics4','ics8'};
  2679.     static const short                kIconSize[6] = {256,   512,   1024,  64,    128,   256   };
  2680.      ODIconFamily icons = ODGetIconFamilyProp(ev, fromSU, kODPropCustomIcon, kODIconFamily, kAllIconsMask);
  2681.     
  2682.     if (icons)
  2683.     {
  2684.         // write icons to the file
  2685.         long    i = 6;
  2686.         do {
  2687.             Handle    icon;
  2688.             char    state;
  2689.             if ((GetIconFromSuite(&icon, icons, kIconType[--i]) == noErr) && (icon != nil))
  2690.             {
  2691.                 state = HGetState(icon);
  2692.                 HLock(icon);
  2693.                 WASSERT(GetHandleSize(icon) == kIconSize[i]);
  2694.                 file->WriteResourcePtr(kIconType[i], kCustomIconResource, *icon, kIconSize[i]);
  2695.                 HSetState(icon, state);
  2696.             }
  2697.         } while (i);
  2698.         file->SetCustomIcon(kODTrue);
  2699.     }
  2700. }
  2701.  
  2702. static void SetFinderInfo(Environment* ev, ODStorageUnit* su, PlatformFile* file)
  2703. {
  2704.     InitDateInfo(ev, su);
  2705.     ODULong modDate = ODGetModificationDate(ev, su);
  2706.     ODULong creationDate = ODGetCreationDate(ev, su);        
  2707.     
  2708.     file->CreateResFile();    
  2709.     file->SetFileModDate(modDate);
  2710.     file->SetFileCreationDate(creationDate);
  2711. //    file->SetStationery(ODGetSUIsStationery(ev, su));
  2712. }
  2713.  
  2714. static OSErr GetDropFSSpec(ODPlatformDragReference theDrag, FSSpec &dropFSSpec)
  2715. {
  2716.     AEDesc    dropDescriptor;
  2717.  
  2718.     OSErr result = GetDropLocation(theDrag, &dropDescriptor);
  2719.     if ((result != noErr) ||
  2720.         (dropDescriptor.descriptorType == typeNull) ||
  2721.         (dropDescriptor.dataHandle == nil))
  2722.     {
  2723.         result = fnfErr;            // Can't create a file unless we know where it goes!
  2724.     }
  2725.     else
  2726.     {
  2727.         AEDesc fssDescriptor;
  2728.         result = AECoerceDesc(&dropDescriptor, typeFSS, &fssDescriptor);
  2729.         AEDisposeDesc(&dropDescriptor);
  2730.         if (result == noErr) {        
  2731.             ODBlockMove(*fssDescriptor.dataHandle, &dropFSSpec, sizeof(FSSpec));
  2732.             AEDisposeDesc(&fssDescriptor);
  2733.  
  2734.             // Use PBGetCatInfo to get the directoryID of the target directory.
  2735.             CInfoPBRec getInfoPB;
  2736.             getInfoPB.dirInfo.ioCompletion = 0L;
  2737.             getInfoPB.dirInfo.ioNamePtr = (StringPtr) &(dropFSSpec.name);
  2738.             getInfoPB.dirInfo.ioVRefNum = dropFSSpec.vRefNum;
  2739.             getInfoPB.dirInfo.ioFDirIndex = 0;
  2740.             getInfoPB.dirInfo.ioDrDirID = dropFSSpec.parID;
  2741.             result = PBGetCatInfoSync(&getInfoPB);
  2742.             if (result == noErr)
  2743.             {
  2744.                 dropFSSpec.parID = getInfoPB.dirInfo.ioDrDirID;
  2745.                 dropFSSpec.name[0] = 0;
  2746.             }
  2747.         }
  2748.     }
  2749.     
  2750.     return result;
  2751. }
  2752.  
  2753. static boolean IsTrashFolder(FSSpec dropFSSpec)
  2754. {
  2755.     short trashVol;
  2756.     long trashDir;
  2757.  
  2758.     return (FindFolder(dropFSSpec.vRefNum,kTrashFolderType,kDontCreateFolder,&trashVol,&trashDir) == noErr) && 
  2759.             (trashVol==dropFSSpec.vRefNum) && (
  2760.             (trashDir==dropFSSpec.parID) );
  2761.  
  2762. }
  2763.  
  2764. static boolean IsFrontProcess()
  2765. {
  2766.     ProcessSerialNumber myProcess, frontProcess;
  2767.     boolean inFront = false;
  2768.  
  2769.     GetCurrentProcess(&myProcess);
  2770.     GetFrontProcess(&frontProcess);
  2771.     SameProcess(&myProcess, &frontProcess, &inFront);
  2772.  
  2773.     return inFront;
  2774. }
  2775.  
  2776. static OSErr CreateReplaceFileEvent(Environment* ev,
  2777.     AppleEvent* replaceFileEvent,
  2778.     ODSession* session,
  2779.     ProcessSerialNumber* psn)
  2780. {
  2781.     OSErr            err = noErr;
  2782.     AEAddressDesc    targetAddress;
  2783.     TempAEDesc        tempTargetAddress = kODNULL;
  2784.     
  2785.     err = AECreateDesc(typeProcessSerialNumber, psn, sizeof(ProcessSerialNumber), &targetAddress);
  2786.  
  2787.     if (err == noErr)
  2788.     {
  2789.         err = AECreateAppleEvent(kODShellSignature, kODReplaceFileEventID, 
  2790.                 &targetAddress, kAutoGenerateReturnID, 
  2791.                 kAnyTransactionID, replaceFileEvent);
  2792.         AEDisposeDesc(&targetAddress);
  2793.     }
  2794.     if ( err == noErr )
  2795.         err = AEPutParamPtr(replaceFileEvent, kODSession, typeLongInteger,
  2796.                             &session, sizeof(ODSession*));
  2797.     return err;
  2798. }
  2799.  
  2800. static OSErr SetupReplaceFileEvent(Environment* ev,
  2801.     AppleEvent* replaceFileEvent,
  2802.     FSSpec* sourceFileSpec,
  2803.     FSSpec* destFileSpec)
  2804. {
  2805.     OSErr err = noErr;
  2806.     if (err == noErr)
  2807.     {
  2808.         err = AEPutParamPtr(replaceFileEvent, kODSourceFileSpec, typeFSS,
  2809.                         sourceFileSpec, sizeof(FSSpec));
  2810.     }
  2811.     if ( err == noErr )
  2812.         err = AEPutParamPtr(replaceFileEvent, kODDestinationFileSpec, typeFSS,
  2813.                             destFileSpec, sizeof(FSSpec));
  2814.  
  2815. #ifdef ODDebug                    
  2816.     if (err != noErr)
  2817.     {
  2818.         WARN("Error in SetupReplaceFileEvent: %d", err);
  2819.     }
  2820. #endif
  2821.  
  2822.     return err;
  2823. }
  2824.  
  2825. static OSErr SendReplaceFileEvent(AppleEvent* replaceFileEvent, ProcessSerialNumber* psn)
  2826. {
  2827.     OSErr        err;
  2828.     AppleEvent    replyAppleEvent;
  2829.     
  2830.     SetFrontProcess(psn);
  2831.     
  2832. //    TempAEDesc tmpReplaceFileAppleEvent(replaceFileEvent);
  2833.     err = AESend(replaceFileEvent, &replyAppleEvent, kAENoReply | kAEInteractWithSelf,
  2834.                         kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  2835.  
  2836. #ifdef ODDebug                    
  2837.     if (err != noErr)
  2838.     {
  2839.         WARN("Error in SendReplaceFileEvent: %d", err);
  2840.     }
  2841. #endif
  2842.                             
  2843.     return err;
  2844. }
  2845.  
  2846. static OSErr DisposeReplaceFileEvent(AppleEvent* replaceFileEvent)
  2847. {
  2848.     return AEDisposeDesc(replaceFileEvent);
  2849. }
  2850.  
  2851. static OSErr ODPascal ReplaceFileAEHandler(
  2852.         const AppleEvent* replaceFileEvent,
  2853.         AppleEvent* reply,
  2854.         long refCon)
  2855. {
  2856.     OSErr        err = noErr;
  2857.     DescType    returnedType;
  2858.     Size        actualSize;
  2859.     FSSpec        sourceFileSpec;
  2860.     FSSpec        destFileSpec;
  2861.     ODSession*    session = kODNULL;
  2862.     
  2863.     err = AEGetParamPtr(replaceFileEvent, kODSession,
  2864.                             typeLongInteger, &returnedType,
  2865.                             &session, sizeof(ODSession*), &actualSize);
  2866.     WASSERTM(actualSize == sizeof(ODSession*), "Incorrect kODSession size");
  2867.     
  2868.     if (err == noErr)
  2869.     {
  2870.         err = AEGetParamPtr(replaceFileEvent, kODDestinationFileSpec,
  2871.                                 typeFSS, &returnedType,
  2872.                                 &destFileSpec, sizeof(FSSpec), &actualSize);
  2873.         WASSERTM(actualSize == sizeof(FSSpec), "Incorrect DestinationFileSpec size");
  2874.     }
  2875.     
  2876.     if (err == noErr)
  2877.     {
  2878.         Environment* ev = somGetGlobalEnvironment();
  2879.         ParamText(destFileSpec.name, "\p", "\p", "\p");
  2880.         err = AEInteractWithUser(kAEDefaultTimeout, NULL, NULL);
  2881.         if ((err == noErr) && ODAskUserReplace(ev, session))
  2882.         {
  2883.             err = AEGetParamPtr(replaceFileEvent, kODSourceFileSpec,
  2884.                                     typeFSS, &returnedType,
  2885.                                     &sourceFileSpec, sizeof(FSSpec), &actualSize);
  2886.             if (err == noErr)
  2887.             {
  2888.                 WASSERTM(actualSize == sizeof(FSSpec), "Incorrect kODSourceFileSpec size");
  2889.                 TempPlatformFile sourceFile = new PlatformFile;
  2890.                 sourceFile->Specify(&sourceFileSpec);
  2891.                 TempPlatformFile destFile = new PlatformFile;
  2892.                 destFile->Specify(&destFileSpec);
  2893.                 
  2894.                 destFile->MoveToTrash();
  2895.                 sourceFile->Move(destFileSpec.parID);
  2896.             }
  2897.         }
  2898.     }
  2899.  
  2900. #ifdef ODDebug
  2901.     if (err != noErr)
  2902.         WARN("Error occured in ReplaceFileAEHandler: %d", err);
  2903. #endif
  2904.  
  2905.     return err;
  2906. }
  2907.  
  2908. static void RespecifyToTempFolder(PlatformFile* file)
  2909. {
  2910.     ODSLong    tempDirID;
  2911.     FSSpec    fsSpec = file->GetFileSpec();
  2912.     
  2913.     THROW_IF_ERROR(FindFolder(fsSpec.vRefNum, kTemporaryFolderType, kCreateFolder,
  2914.                             &(fsSpec.vRefNum), &tempDirID));
  2915.     fsSpec.parID = tempDirID;
  2916.     file->Specify(&fsSpec);
  2917.     if (file->Exists())
  2918.         file->Delete();
  2919. }
  2920.  
  2921. static ODBoolean IsOpenDocDocument(HFSFlavor* hfsFlavor)
  2922. {
  2923.     return PlatformFile::IsOpenDocDocument(hfsFlavor->fileType,hfsFlavor->fileCreator);
  2924. }
  2925.  
  2926. static ODBoolean IsOpenDocClipping( HFSFlavor* hfsFlavor) 
  2927. {
  2928.     ODBoolean isOpenDocClipping = kODFalse;    
  2929.     OSType theFileType = hfsFlavor->fileType;
  2930.     
  2931.     // Check if the clipping came from the drag manager.
  2932.     if( hfsFlavor->fileCreator == 'drag' )
  2933.     {
  2934.         // Now check if it has the file type 'clp≈' where ≈ is any lower case letter.
  2935.         ODUByte* tempPtr = (ODUByte*)&theFileType;
  2936.         if( ( tempPtr[0] == 'c' ) && ( tempPtr[1] == 'l' ) &&
  2937.             ( tempPtr[2] == 'p' ) && ( islower( tempPtr[3] ) ) )
  2938.         {
  2939.             OSErr theErr;
  2940.             short oldResRefnum;
  2941.             short clippingRefNum;
  2942.             ODHandle tempHandle = kODNULL;
  2943.             
  2944.             // Now check if there is a resource of type kODBentoFlavor
  2945.             oldResRefnum = CurResFile();
  2946.             // Open the clipping's resource fork.
  2947.             SetResLoad(false);        // Inside Mac says to make the SetResLoad calls before & after the OpenResFile call.
  2948.                                     // We probably don't need to do this in our case, but I'm paranoid today.
  2949.             clippingRefNum = FSpOpenResFile(&(hfsFlavor->fileSpec), fsCurPerm);
  2950.             SetResLoad(true);
  2951.             theErr = ResError();
  2952.             if( theErr == noErr )
  2953.             {
  2954.                 short numODCN = Count1Resources(kODBentoFlavor);
  2955.                 if( numODCN ==1 )        // the clipping has the Bento container data
  2956.                     isOpenDocClipping = kODTrue;
  2957.                 FSClose( clippingRefNum );
  2958.             }
  2959.             SetResLoad(true);        
  2960.             UseResFile(oldResRefnum);
  2961.         }
  2962.     }
  2963.     
  2964.     return isOpenDocClipping;
  2965. }
  2966.  
  2967. static ODHandle ReadClippingFileOpenDocData( HFSFlavor* hfsFlavor )
  2968. {
  2969.     OSErr theErr;
  2970.     short oldResRefnum;
  2971.     short clippingRefNum;
  2972.     ODHandle tempHandle = kODNULL;
  2973.     
  2974.     oldResRefnum = CurResFile();
  2975.     // Open the clipping's resource fork.
  2976.     SetResLoad(false);        // Inside Mac says to make the SetResLoad calls before & after the OpenResFile call.
  2977.         clippingRefNum = FSpOpenResFile(&(hfsFlavor->fileSpec), fsCurPerm);
  2978.     SetResLoad(true);        // We probably don't need to do this, but I'm paranoid today.
  2979.     theErr = ResError();
  2980.     if( theErr == noErr )
  2981.     {                                
  2982.         // The clipping has the data in a resource of the same name as the drag flavor, which
  2983.         // in our case is the the constant kODBentoFlavor.
  2984.         tempHandle = (ODHandle)BasicReadResource( clippingRefNum,kODBentoFlavor,1,kODNULL,1);
  2985.         FSClose( clippingRefNum );
  2986.     }
  2987.     if( theErr != noErr )
  2988.     {
  2989.         UseResFile(oldResRefnum);
  2990.         THROW( theErr );
  2991.     }
  2992.     
  2993.     UseResFile(oldResRefnum);
  2994.     return tempHandle;
  2995. }
  2996.